Decompiled source of ZenRedecorate v0.2.20
plugins\ZenRedecorate.dll
Decompiled 8 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.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Jotunn; using Jotunn.Configs; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.LowLevel; using UnityEngine.SceneManagement; using UnityEngine.UI; using Valheim.SettingsGui; using ZenModLib; using ZenModLib.Controls; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ZenRedecorate")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ZenRedecorate")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.0")] [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 ZenModLib { internal static class AssetIO { public static Sprite LoadSprite(string resourceName) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, LoadResource(resourceName)); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } private static byte[] LoadResource(string resourceName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); Type type = ((object)ZenPlugin.Instance).GetType(); using Stream stream = executingAssembly.GetManifestResourceStream(type.Namespace + ".Resources." + resourceName); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } [HarmonyPatch] internal static class Cleanup { public static void External() { ConfigTomlTypeConverterEntries(); JotunnConfigs(); } private static void JotunnConfigs() { ConfigFile config = ((BaseUnityPlugin)ZenPlugin.Instance).Config; Log.Debug("Remove config entries from Jotunn cache", "JotunnConfigs", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Cleanup.cs"); Dictionary<ConfigEntryBase, object> dictionary = (Dictionary<ConfigEntryBase, object>)AccessTools.Field(typeof(SynchronizationManager), "localValues").GetValue(SynchronizationManager.Instance); foreach (ConfigDefinition key2 in config.Keys) { ConfigEntryBase key = config[key2]; dictionary.Remove(key); } } private static void ConfigTomlTypeConverterEntries() { Log.Debug("Removing TomlTypeConverter Entry: StringList", "ConfigTomlTypeConverterEntries", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Cleanup.cs"); ((Dictionary<Type, TypeConverter>)AccessTools.Property(typeof(TomlTypeConverter), "TypeConverters").GetValue(null)).Remove(typeof(Config.StringList)); } } public static class Config { public class StringList : List<string> { internal static readonly Tally<string> AccessCount; public static StringList Empty => new StringList(); public StringList(params IEnumerable<string>[] collections) { foreach (IEnumerable<string> collection in collections) { AddRange(collection); } } public new string ToString() { return string.Join(", ", this); } public static StringList Parse(string? str) { if (str == null) { return Empty; } string[] source = str.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); return new StringList(source.Select((string s) => s.Trim())); } static StringList() { //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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown AccessCount = new Tally<string>(); TomlTypeConverter.AddConverter(typeof(StringList), new TypeConverter { ConvertToString = (object obj, Type _) => ((StringList)obj).ToString(), ConvertToObject = delegate(string str, Type _) { CheckPerformance(str); return Parse(str); static void CheckPerformance(string s) { if (!string.IsNullOrEmpty(s)) { AccessCount[s]++; if (AccessCount[s] > 2) { Log.Warning("Possible performance issue. (ConfigWatcher maybe?) " + $"ConvertToObject access count {AccessCount[s]} > {2}: \"{s}\"", ".cctor", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Config.cs"); } } } } }); } public IEnumerable<string[]> Split(char splitChar = ':', bool trim = true) { List<string[]> list = new List<string[]>(); using List<string>.Enumerator enumerator = GetEnumerator(); while (enumerator.MoveNext()) { string[] array = enumerator.Current.Split(new char[1] { splitChar }); if (trim) { array = array.Select((string s) => s.Trim()).ToArray(); } list.Add(array); } return list; } public (string Name, string Value)[] ToTuple(char splitChar = ':') { return (from element in Split(splitChar) select (element[0], element[1])).ToArray(); } public Requirement[] ToRequirements() { return ((IEnumerable<RequirementConfig>)ToRequirementConfigs()).Select((Func<RequirementConfig, Requirement>)((RequirementConfig config) => new Requirement { m_resItem = ObjectDB.instance.GetItemPrefab(config.Item).GetComponent<ItemDrop>(), m_amount = config.Amount, m_amountPerLevel = config.AmountPerLevel, m_recover = config.Recover })).ToArray(); } public RequirementConfig[] ToRequirementConfigs() { return Split().Select<string[], RequirementConfig>((Func<string[], RequirementConfig>)((string[] element) => new RequirementConfig(element[0], int.Parse(element[1]), (element.Length > 2) ? int.Parse(element[2]) : 0, element.Length <= 3 || bool.Parse(element[3])))).ToArray(); } } internal static AcceptableValueBase AcceptRange<T>(T min, T max) where T : IComparable { return (AcceptableValueBase)(object)new AcceptableValueRange<T>(min, max); } internal static AcceptableValueBase AcceptList<T>(params T[] list) where T : IEquatable<T> { return (AcceptableValueBase)(object)new AcceptableValueList<T>(list); } internal static ConfigEntry<T> DefineConfig<T>(bool isAdmin, string section, string key, T defaultValue, AcceptableValueBase? acceptableValues = null, string description = "") { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown return ((BaseUnityPlugin)ZenPlugin.Instance).Config.Bind<T>(section, key, defaultValue, new ConfigDescription((isAdmin ? "[Admin] " : "") + description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = isAdmin } })); } } public static class FireplaceExt { public static int FuelDays(this Fireplace fireplace, float? fuel = null) { float valueOrDefault = fuel.GetValueOrDefault(); if (!fuel.HasValue) { valueOrDefault = fireplace.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f); fuel = valueOrDefault; } return UI.RealToGameTime(fuel.Value * fireplace.m_secPerFuel).Days; } public static int FuelDaysMax(this Fireplace fireplace) { return UI.RealToGameTime(fireplace.m_maxFuel * fireplace.m_secPerFuel).Days; } public static bool IsFuelDaysFull(this Fireplace fireplace, float? fuel = null) { if (fireplace.m_infiniteFuel) { return true; } int num = fireplace.FuelDays(fuel); if (num > 0) { return num >= fireplace.FuelDaysMax(); } return false; } public static bool IsFuelDaysEmpty(this Fireplace fireplace, float? fuel = null) { if (!fireplace.m_infiniteFuel) { return fireplace.FuelDays(fuel) <= 0; } return false; } public static bool IsFuelEmpty(this Fireplace fireplace) { if (!fireplace.m_infiniteFuel) { return fireplace.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f) <= 0f; } return false; } } internal static class HudExt { public static void UpdateHoverIcons(this Hud hud, params (Sprite Icon, string Label)[] elements) { ((Component)hud).SendMessage("UpdateHoverIcons", (object)elements, (SendMessageOptions)1); } public static void UpdateHoverIcons(this Hud hud, params (string prefabName, string Label)[] elements) { ((Component)hud).SendMessage("UpdateHoverIcons", (object)elements, (SendMessageOptions)1); } public static void UpdateHoverIcons(this Hud hud, params Sprite[] sprites) { ((Component)hud).SendMessage("UpdateHoverIcons", (object)sprites, (SendMessageOptions)1); } public static void UpdateHoverIcons(this Hud hud, params string[] prefabNames) { ((Component)hud).SendMessage("UpdateHoverIcons", (object)prefabNames, (SendMessageOptions)1); } } public static class HumanoidExt { public static MonoBehaviour? GetHoverInteractable(this Humanoid self) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown GameObject hoverObject = self.GetHoverObject(); return (MonoBehaviour)(Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<Interactable>() : null); } public static bool IsUnarmed(this Humanoid self) { if (self.GetLeftItem() == null) { return self.GetRightItem() == null; } return false; } public static bool IsUsingRangedWeapon(this Humanoid self) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 if (self.IsUnarmed()) { return false; } ItemData currentWeapon = self.GetCurrentWeapon(); AttackType attackType = currentWeapon.m_shared.m_attack.m_attackType; if (((int)attackType == 2 || (int)attackType == 5) ? true : false) { return true; } ItemType itemType = currentWeapon.m_shared.m_itemType; if ((int)itemType != 3 && (int)itemType != 14) { return (int)itemType != 22; } return false; } public static bool IsUsingTool(this Humanoid self, bool includeFishigRod) { if (!self.RightItem.IsItemType((ItemType)19) && !self.LeftItem.IsItemType((ItemType)19)) { if (includeFishigRod) { return self.GetCurrentWeapon()?.GetName() == "$item_fishingrod"; } return false; } return true; } public static bool IsUsingPickAxe(this Humanoid self) { if (!IsPickAxe(self.RightItem)) { return IsPickAxe(self.LeftItem); } return true; static bool IsPickAxe(ItemData? item) { if (item != null) { return item.m_shared.m_damages.m_pickaxe > 0f; } return false; } } } public static class IEnumerableExt { public static IEnumerable<(T Item, int Index)> WithIndex<T>(this IEnumerable<T> self) { return self.Select((T obj, int index) => (obj, index)); } } public static class ItemDataExt { public static bool IsItemType(this ItemData? item, ItemType type) { //IL_000b: 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) if (item == null) { return false; } return item.m_shared.m_itemType == type; } public static bool IsStackable(this ItemData item) { return item.m_shared.m_maxStackSize > 1; } public static bool IsStackable(this ItemDrop item) { return item.m_itemData.m_shared.m_maxStackSize > 1; } public static string GetPrefabName(this ItemDrop itemDrop) { return Utils.GetPrefabName(((Object)itemDrop).name); } public static string GetPrefabName(this ItemData item) { if (!Object.op_Implicit((Object)(object)item.m_dropPrefab)) { return ((Object)ObjectDB.instance.GetItemPrefab(item.m_shared)).name; } return ((Object)item.m_dropPrefab).name; } public static string GetName(this ItemData item) { return item.m_shared.m_name; } public static string GetName(this ItemDrop item) { return item.m_itemData.m_shared.m_name; } public static Sprite GetIcon(this ItemData item, int variant) { return item.m_shared.m_icons[variant]; } public static Sprite GetIcon(this ItemDrop item) { return item.m_itemData.GetIcon(); } public static Sprite GetIcon(this ItemDrop item, int variant) { return item.m_itemData.GetIcon(variant); } public static int GetStableHashCode(this ItemDrop item) { return StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Object)item).name)); } public static bool IsEqual(this ItemData item, ItemData other) { if (!(((Object)item.m_dropPrefab).name == ((Object)other.m_dropPrefab).name) || !(item.GetName() == other.GetName()) || item.m_variant != other.m_variant || item.m_quality != other.m_quality || !Mathf.Approximately(item.m_durability, other.m_durability)) { return false; } foreach (KeyValuePair<string, string> customDatum in item.m_customData) { if (!other.m_customData.TryGetValue(customDatum.Key, out var value)) { return false; } if (value != customDatum.Value) { return false; } } return true; } public static bool HaveItemData(this Inventory inventory, ItemData itemData) { foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.IsEqual(itemData)) { return true; } } return false; } public static void SwapItem(this Inventory thisInv, ItemData thisItem, Inventory otherInv, ItemData otherItem) { //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) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Vector2i gridPos = thisItem.m_gridPos; Vector2i gridPos2 = otherItem.m_gridPos; bool equipped = thisItem.m_equipped; bool equipped2 = otherItem.m_equipped; thisInv.RemoveItem(thisItem); otherInv.RemoveItem(otherItem); thisInv.AddItem(otherItem, gridPos); otherInv.AddItem(thisItem, gridPos2); Player player = Player.m_localPlayer; if (equipped) { SwitchEquipped(thisItem, otherItem); } else if (equipped2) { SwitchEquipped(otherItem, thisItem); } void SwitchEquipped(ItemData a, ItemData b) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) ((Humanoid)player).UnequipItem(a, false); if (a.m_shared.m_itemType == b.m_shared.m_itemType || (a.IsWeapon() && b.IsWeapon())) { ((Humanoid)player).EquipItem(b, false); } } } } public static class ItemStandExt { public static bool IsBossStone(this ItemStand itemStand) { return Object.op_Implicit((Object)(object)itemStand.m_guardianPower); } public static bool CanBeRemoved(this ItemStand itemStand) { return itemStand.m_canBeRemoved; } } public static class MathExt { public static bool InRange(this GameObject self, GameObject target, float range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(self.transform.position - target.transform.position) < range * range; } public static bool InRange(this GameObject self, Vector3 target, float range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(self.transform.position - target) < range * range; } public static bool InRange(this MonoBehaviour self, Vector3 target, float range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(((Component)self).transform.position - target) < range * range; } public static bool InRange(this MonoBehaviour self, MonoBehaviour target, float range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(((Component)self).transform.position - ((Component)target).transform.position) < range * range; } public static bool InRange(this MonoBehaviour self, GameObject target, float range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(((Component)self).transform.position - target.transform.position) < range * range; } public static float DistanceToSqr(this GameObject self, Vector3 target) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(self.transform.position - target); } public static float DistanceToSqr(this MonoBehaviour self, MonoBehaviour target) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(((Component)self).transform.position - ((Component)target).transform.position); } public static float DistanceToSqr(this MonoBehaviour self, Vector3 target) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(((Component)self).transform.position - target); } public static float DistanceToSqr(this Vector3 source, Vector3 target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(source - target); } public static float DistanceToXZ(this GameObject self, GameObject target) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) return self.transform.position.DistanceToXZ(target.transform.position); } public static float DistanceToXZ(this MonoBehaviour self, MonoBehaviour target) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) return ((Component)self).transform.position.DistanceToXZ(((Component)target).transform.position); } public static float DistanceToXZ(this MonoBehaviour self, Vector3 target) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) return ((Component)self).transform.position.DistanceToXZ(target); } public static float DistanceToXZ(this Vector3 source, Vector3 target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) Vector3 val = source; val.y = 0f; Vector3 val2 = val; val = target; val.y = 0f; return Vector3.Distance(val2, val); } public static float DistanceTo(this GameObject self, GameObject target) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) return self.transform.position.DistanceTo(target.transform.position); } public static float DistanceTo(this MonoBehaviour self, MonoBehaviour target) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) return ((Component)self).transform.position.DistanceTo(((Component)target).transform.position); } public static float DistanceTo(this MonoBehaviour self, Vector3 target) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) return ((Component)self).transform.position.DistanceTo(target); } public static float DistanceTo(this Vector3 source, Vector3 target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(source, target); } public static bool Approximately(this Vector3 self, Vector3 other) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(self - other) < 0.0001f; } public static Vector3 XZY(this Vector3 self) { //IL_0000: 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) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(self.x, self.z, self.y); } public static float DistanceToPlayer(this Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return position.DistanceToCharacter((Character)(object)Player.m_localPlayer); } public static float DistanceToCharacter(this Vector3 position, Character c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Mathf.Sqrt(position.DistanceToCharacterSqr(c)); } public static float DistanceToCharacterSqr(this Vector3 position, Character c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return Vector3.SqrMagnitude(((Component)c).transform.position - position); } public static float AngleFromPlayer(this Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return position.AngleFromCharacter((Character)(object)Player.m_localPlayer); } public static float AngleFromCharacter(this Vector3 position, Character c) { //IL_0007: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)c).transform; Vector3 val = position - transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; return Vector3.SignedAngle(transform.forward, normalized, Vector3.up); } public static float AngleFromCamera(this Vector3 position) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)GameCamera.instance.m_camera).transform; Vector3 val = position - transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; return Vector3.SignedAngle(transform.forward, normalized, Vector3.up); } public static float AlignmentRatioTo(this Transform transform, Vector3 destPosition) { //IL_0000: 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) Vector3 val = destPosition - transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; return Vector3.Dot(transform.forward, normalized); } } public static class MessageHudExt { public static void ShowMessage(this MessageHud msgHud, long targetPeerID, MessageType type, string text) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected I4, but got Unknown ZRoutedRpc.instance.InvokeRoutedRPC(targetPeerID, "ShowMessage", new object[2] { (int)type, text }); } } public static class PlayerExt { public static bool IsReady(this Player? player) { if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead()) { return !((Character)player).IsTeleporting(); } return false; } public static bool Is(this Player? player, Character other) { if (player.IsReady()) { return (Object)(object)player == (Object)(object)other; } return false; } public static void SelectRepairTool(this Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) player.SetSelectedPiece(Vector2Int.zero); } public static void RemoveGuardianPower(this Player player) { player.m_guardianPower = string.Empty; player.m_guardianPowerHash = 0; player.m_guardianSE = null; } } public static class StringExt { public static string ToHumanString(this int num) { if (num >= 1000000) { if (num >= 1000000000) { return "∞"; } return $"{Mathf.Round((float)num / 1000000f):0}M"; } if (num >= 10000) { return $"{Mathf.Round((float)num / 1000f):0}K"; } return num.ToString(); } public static string Localize(this string? s) { return Localization.instance.Localize(s); } public static string ToProperCase(this string? str) { return str?[0].ToString().ToUpper() + str?.Substring(1).ToLower(); } public static string RegexPattern(this string? pattern, bool localize = true) { return pattern.RegexPattern((string s) => s, localize); } public static string RegexPattern(this string? pattern, Func<string, string> func, bool localize = true) { return Regex.Escape(func(localize ? pattern.Localize() : (pattern ?? string.Empty))); } public static string GlyphFix(this string s, bool onlyIfGamepad = true) { if (!ZInput.IsGamepadActive() && onlyIfGamepad) { return s; } return s.Replace("[<color=yellow><b><sprite=", "<sprite=").Replace("\"></b></color>]", "\">"); } } public static class WardAccessExt { public static bool CanAccessWard(this GameObject self, bool flash) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return self.transform.position.CanAccessWard(flash); } public static bool CanAccessWard(this MonoBehaviour self, bool flash) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((Component)self).transform.position.CanAccessWard(flash); } public static bool CanAccessWard(this Vector3 self, bool flash) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return PrivateArea.CheckAccess(self, 0f, flash, false); } } public static class ZdoExt { private static readonly int ZdoKeyEpochStart = StringExtensionMethods.GetStableHashCode("Zen_EpochStart"); private static bool HasEpoch(this ZDO zdo) { return zdo.GetEpoch() != 0.0; } private static double GetEpoch(this ZDO zdo) { return zdo.GetDouble(ZdoKeyEpochStart); } public static float GetAgeSeconds(this ZDO zdo) { return (float)(ZNet.instance.GetTimeSeconds() - zdo.GetEpoch()); } public static void AccelerateAge(this ZDO zdo, float seconds) { if (!zdo.IsOwner()) { Log.Error("Cannot age this ZDO, not owner.", "AccelerateAge", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZdoExt.cs"); return; } double value = Math.Max(zdo.GetEpoch() - (double)seconds, 0.0); zdo.Set(ZdoKeyEpochStart, value); } public static void RemoveEpoch(this ZDO zdo) { if (!zdo.IsOwner()) { Log.Error("Cannot remove epoch time because not owner of this ZDO.", "RemoveEpoch", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZdoExt.cs"); } else { zdo.Set(ZdoKeyEpochStart, 0.0); } } public static void InitEpoch(this ZDO zdo) { if (!zdo.IsOwner()) { Log.Error("Cannot init epoch time because not owner of this ZDO.", "InitEpoch", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZdoExt.cs"); } else if (!zdo.HasEpoch()) { zdo.Set(ZdoKeyEpochStart, ZNet.instance.GetTimeSeconds()); } } public static string GetPrefabName(this ZDO zdo) { return ((Object)ZNetScene.instance.GetPrefab(zdo.GetPrefab())).name; } public static double GetDouble(this ZDO zdo, string name, double defaultValue = 0.0) { return zdo.GetDouble(StringExtensionMethods.GetStableHashCode(name), defaultValue); } public static double GetDouble(this ZDO zdo, int hash, double defaultValue = 0.0) { long num = BitConverter.DoubleToInt64Bits(defaultValue); return BitConverter.Int64BitsToDouble(zdo.GetLong(hash, num)); } public static void Set(this ZDO zdo, string name, double value) { zdo.Set(StringExtensionMethods.GetStableHashCode(name), value); } public static void Set(this ZDO zdo, int hash, double value) { long num = BitConverter.DoubleToInt64Bits(value); zdo.Set(hash, num); } } public static class ZInputExt { public static string Path(this GamepadInput g) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return ZInput.s_gamepadInputPathMap[g]; } public static string Path(this MouseButton m) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ZInput.MouseButtonToPath(m, true); } public static string Path(this KeyCode k) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ZInput.KeyCodeToPath(k, false); } public static string Path(this Key k) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ZInput.KeyToPath(k); } public static ButtonDef GetButtonDef(this ZInput self, ActionString actionString) { return self.GetButtonDef(actionString.Name); } public static bool RemoveButton(this ZInput self, string name) { if (!self.m_buttons.TryGetValue(name, out var value)) { return false; } Log.Info("Remove Button: " + name, "RemoveButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZInputExt.cs"); self.UnsubscribeButton(value); self.m_buttons.Remove(value.Name); return true; } private static bool RemapToPath(this ButtonDef self, string newPath, bool? altKey = null, bool? showHints = null, bool? rebindable = null, float? repeatDelay = null, float? repeatInterval = null) { if (self.GetActionPath(true) == newPath && (!altKey.HasValue || altKey == self.AltKey) && (!showHints.HasValue || showHints == self.ShowHints) && (!rebindable.HasValue || rebindable == self.Rebindable) && (!repeatDelay.HasValue || Mathf.Approximately(repeatDelay.Value, self.m_repeatDelay)) && (!repeatInterval.HasValue || Mathf.Approximately(repeatInterval.Value, self.m_repeatInterval))) { return false; } self.Rebind(newPath); if (altKey.HasValue) { self.AltKey = altKey.Value; } if (showHints.HasValue) { self.ShowHints = showHints.Value; } if (rebindable.HasValue) { self.Rebindable = rebindable.Value; } if (repeatDelay.HasValue) { self.m_repeatDelay = repeatDelay.Value; } if (repeatInterval.HasValue) { self.m_repeatInterval = repeatInterval.Value; } return true; } public static bool RemapTo(this ButtonDef self, KeyCode newInput, bool? altKey = null, bool? showHints = null, bool? rebindable = null, float? repeatDelay = null, float? repeatInterval = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return self.RemapToPath(newInput.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval); } public static bool RemapTo(this ButtonDef self, GamepadInput newInput, bool? altKey = null, bool? showHints = null, bool? rebindable = null, float? repeatDelay = null, float? repeatInterval = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return self.RemapToPath(newInput.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval); } public static string GetGamepadPlatform(this ZInput zi) { //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_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected I4, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 GamepadGlyphs currentGlyph = ZInput.CurrentGlyph; switch ((int)currentGlyph) { case 0: { GamepadType connectedGamepadType = ZInput.ConnectedGamepadType; return ((int)connectedGamepadType == 3) ? "xbox" : ((connectedGamepadType - 4 > 1) ? "xbox" : "ps5"); } case 1: return "xbox"; case 2: return "ps5"; default: return "xbox"; } } public static string GetGamepadSpriteName(this ZInput zi, GamepadInput gamepadInput, string platform) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) string key = zi.MapKeyFromPath(ZInput.s_gamepadInputPathMap[gamepadInput]); return ZInput.s_gamepadSpriteMap[key][platform]; } public static string GetSpriteTag(this ZInput zi, GamepadInput gamepadInput) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) string gamepadPlatform = zi.GetGamepadPlatform(); string gamepadSpriteName = zi.GetGamepadSpriteName(gamepadInput, gamepadPlatform); return "<sprite=\"" + gamepadPlatform + "\" name=\"" + gamepadSpriteName + "\">"; } } public static class ZRoutedRpcExt { public static void Unregister(this ZRoutedRpc? zrpc, string name) { if (zrpc != null && zrpc.m_functions.Remove(StringExtensionMethods.GetStableHashCode(name))) { Log.Info("Unregistered RPC: " + name, "Unregister", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Extensions\\ZRoutedRpcExt.cs"); } } } [HarmonyPatch] public static class FixVanilla { [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "AddUniqueKey")] private static IEnumerable<CodeInstruction> Player_AddUniqueKey_Transpiler(IEnumerable<CodeInstruction> codes) { MethodInfo methodInfo = AccessTools.Method(typeof(HashSet<string>), "Contains", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(FixVanilla), "HashSet_Contains_Intercept", (Type[])null, (Type[])null); return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2); } private static bool HashSet_Contains_Intercept(HashSet<string> self, string? item) { Log.Info("Fixed: Player key can not be blank", "HashSet_Contains_Intercept", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\FixVanilla.cs"); self.Remove(string.Empty); self.Remove(null); if (!Utility.IsNullOrWhiteSpace(item)) { return self.Contains(item); } return true; } } public interface IRedecorate { void OnRedecorateBefore(); void OnRedecorateAfter((Vector3 Position, Quaternion Rotation) before); } public enum HintType { Build, Combat, Bow, Inventory, Barber, Fishing, Radial } [HarmonyPatch] public static class KeyHint { private static HintType _activeType; private static readonly Dictionary<string, (GameObject Keyboard, GameObject Gamepad)> AllHints = new Dictionary<string, (GameObject, GameObject)>(); private const string Section = "_SECTION_"; private static readonly string[] ControlPaths = new string[2] { "Keyboard/_SECTION_/Text", "Gamepad/Text - _SECTION_" }; private static float _lastUpdateTime; private const float _updateDelay = 0.1f; public static event Action? UpdateBuildHints; public static event Action? UpdateCombatHints; public static event Action? UpdateBowHints; public static event Action? UpdateInventoryHints; public static event Action? UpdateBarberHints; public static event Action? UpdateFishingHints; public static event Action? UpdateRadialHints; internal static void RemoveAll() { foreach (var value in AllHints.Values) { Object.Destroy((Object)(object)value.Keyboard); Object.Destroy((Object)(object)value.Gamepad); } AllHints.Clear(); KeyHint.UpdateBuildHints = null; KeyHint.UpdateCombatHints = null; KeyHint.UpdateBowHints = null; KeyHint.UpdateInventoryHints = null; KeyHint.UpdateBarberHints = null; KeyHint.UpdateFishingHints = null; KeyHint.UpdateRadialHints = null; } private static GameObject GetHintRoot(HintType hintType) { return (GameObject)(hintType switch { HintType.Build => KeyHints.instance.m_buildHints, HintType.Combat => KeyHints.instance.m_combatHints, HintType.Bow => KeyHints.instance.m_combatHints, HintType.Inventory => KeyHints.instance.m_inventoryHints, HintType.Barber => KeyHints.instance.m_barberHints, HintType.Fishing => KeyHints.instance.m_fishingHints, HintType.Radial => KeyHints.instance.m_radialHints, _ => throw new ArgumentOutOfRangeException("hintType", hintType, null), }); } public static void Create(HintType hintType, ActionString action, int index = -1, bool startVisible = false) { Create(hintType, action.Name, index, startVisible); } public static void Create(HintType hintType, string hintName, int index = -1, bool startVisible = false) { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) GameObject hintRoot = GetHintRoot(hintType); (GameObject, GameObject) value = default((GameObject, GameObject)); Transform val = hintRoot.transform.Find("Keyboard"); GameObject val2 = Object.Instantiate<GameObject>(((Component)val.GetChild(0)).gameObject, val); if (index >= 0) { val2.transform.SetSiblingIndex(index); } ((Object)val2).name = hintName; ((Component)val2.transform.Find("Text")).GetComponent<TMP_Text>().text = "$" + hintName; ((Component)val2.transform.Find("key_bkg/Key")).GetComponent<TMP_Text>().text = "$KEY_" + hintName; value.Item1 = val2; val2.SetActive(startVisible); Transform val3 = hintRoot.transform.Find("Gamepad"); GameObject val4 = Object.Instantiate<GameObject>(((Component)val3.GetChild(0)).gameObject, val3); if (index >= 0) { val4.transform.SetSiblingIndex(index); } ((Object)val4).name = "Text - " + hintName; val4.GetComponent<TMP_Text>().text = "$" + hintName + " <mspace=0.6em>$KEY_Joy" + hintName + "</mspace>"; value.Item2 = val4; foreach (Transform item in val3) { ((Object)item).name = ((Object)item).name.Replace("/", "-"); } val4.SetActive(startVisible); AllHints.Add(hintName, value); Localization.instance.Localize(hintRoot.transform); } public static void SetVisible(ActionString action, bool isVisible) { SetVisible(_activeType, action.Name, isVisible); } public static void SetVisible(string hintName, bool isVisible) { SetVisible(_activeType, hintName, isVisible); } private static void SetVisible(HintType hintType, string hintName, bool isVisible, string[]? searchPaths = null) { string[] array = searchPaths ?? ControlPaths; foreach (string text in array) { bool flag = text.StartsWith("Gamepad"); if (flag && hintName == "Copy") { SetVisible(hintType, "Copy Alt1-2", isVisible && ZInput.IsNonClassicFunctionality(), new string[1] { text }); SetVisible(hintType, "Copy Default", isVisible && !ZInput.IsNonClassicFunctionality(), new string[1] { text }); break; } string text2 = text.Replace("_SECTION_", hintName); Transform val = GetHintRoot(hintType).transform.Find(text2); if (!Object.op_Implicit((Object)(object)val)) { Log.Error("Node not found: " + text2, "SetVisible", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\KeyHint.cs"); break; } if (flag) { ((Component)val).gameObject.SetActive(isVisible); } else { ((Component)val.parent).gameObject.SetActive(isVisible); } } } [HarmonyPostfix] [HarmonyPatch(typeof(KeyHints), "UpdateHints")] private static void KeyHints_UpdateHints(KeyHints __instance) { if (__instance.m_keyHintsEnabled && (UI.IsOpen || !(Time.time < _lastUpdateTime + 0.1f))) { _lastUpdateTime = Time.time; if (__instance.m_buildHints.activeSelf) { _activeType = HintType.Build; KeyHint.UpdateBuildHints?.Invoke(); } if (__instance.m_inventoryHints.activeSelf) { _activeType = HintType.Inventory; KeyHint.UpdateInventoryHints?.Invoke(); } if (__instance.m_combatHints.activeSelf) { _activeType = HintType.Combat; KeyHint.UpdateCombatHints?.Invoke(); } if (__instance.m_combatHints.activeSelf && ((Humanoid)(object)Player.m_localPlayer).IsUsingRangedWeapon()) { _activeType = HintType.Bow; KeyHint.UpdateBowHints?.Invoke(); } if (__instance.m_fishingHints.activeSelf) { _activeType = HintType.Fishing; KeyHint.UpdateFishingHints?.Invoke(); } if (__instance.m_barberHints.activeSelf) { _activeType = HintType.Barber; KeyHint.UpdateBarberHints?.Invoke(); } if (__instance.m_radialHints.activeSelf) { _activeType = HintType.Radial; KeyHint.UpdateRadialHints?.Invoke(); } } } } internal static class Log { private static readonly LogLevel LogLevels; private static bool IsEnabled { get { if (Object.op_Implicit((Object)(object)ZenPlugin.Instance)) { return ZenPlugin.IsLogEnabled.Value; } return false; } } private static ManualLogSource Logger => ZenPlugin.InstanceLogger; static Log() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<LogLevel> val = default(ConfigEntry<LogLevel>); if (!((ConfigFile)AccessTools.Property(typeof(ConfigFile), "CoreConfig").GetValue(null)).TryGetEntry<LogLevel>("Logging.Disk", "LogLevels", ref val)) { throw new Exception("Log levels config info missing"); } LogLevels = val.Value; } private static string Format(object data, string caller, string filePath) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); return $"[{fileNameWithoutExtension}.{caller}] {data}"; } public static void Debug(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "") { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (IsEnabled && ((Enum)LogLevels).HasFlag((Enum)(object)(LogLevel)32)) { Logger.LogDebug((object)Format(data, caller, filePath)); } } public static void Info(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "") { if (IsEnabled) { Logger.LogInfo((object)Format(data, caller, filePath)); } } public static void Message(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "") { Logger.LogMessage((object)Format(data, caller, filePath)); } public static void Warning(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "") { Logger.LogWarning((object)Format(data, caller, filePath)); } public static void Error(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "") { Logger.LogError((object)Format(data, caller, filePath)); } public static void Fatal(object data, [CallerMemberName] string caller = "", [CallerFilePath] string filePath = "") { Logger.LogFatal((object)Format(data, caller, filePath)); } } internal static class Secure { public static string Encrypt(string plainText, byte[] key, Encoding? encoding = null) { return Convert.ToBase64String(Encrypt((encoding ?? Encoding.UTF8).GetBytes(plainText), key).ToArray()); } public static byte[] Encrypt(byte[] input, byte[] key) { using Aes aes = Aes.Create(); aes.Key = key; using ICryptoTransform cryptoTransform = aes.CreateEncryptor(); byte[] collection = cryptoTransform.TransformFinalBlock(input, 0, input.Length); List<byte> list = new List<byte>(); list.AddRange(aes.IV); list.AddRange(collection); aes.Clear(); return list.ToArray(); } public static string Decrypt(string cipherBase64, byte[] key, Encoding? encoding = null) { byte[] bytes = Decrypt(Convert.FromBase64String(cipherBase64), key); return (encoding ?? Encoding.UTF8).GetString(bytes); } public static byte[] Decrypt(byte[] input, byte[] key) { try { using Aes aes = Aes.Create(); aes.Key = key; aes.IV = input.Take(aes.BlockSize / 8).ToArray(); byte[] array = input.Skip(aes.IV.Length).ToArray(); using ICryptoTransform cryptoTransform = aes.CreateDecryptor(); byte[] result = cryptoTransform.TransformFinalBlock(array, 0, array.Length); aes.Clear(); return result; } catch { return Array.Empty<byte>(); } } public static byte[] GenerateAesKey() { using Aes aes = Aes.Create(); return aes.Key; } public static byte[] DeriveKey(string password, byte[] salt, int iterations = 10000, int keyLength = 32) { using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, iterations); return rfc2898DeriveBytes.GetBytes(keyLength); } public static byte[] GenerateSalt(int saltLength = 32) { using RNGCryptoServiceProvider rNGCryptoServiceProvider = new RNGCryptoServiceProvider(); byte[] array = new byte[saltLength]; rNGCryptoServiceProvider.GetBytes(array); return array; } public static byte[] FromHexStringToBytes(this string hexString) { try { byte[] array = new byte[hexString.Length / 2]; for (int i = 0; i < array.Length; i++) { array[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); } return array; } catch { throw new InvalidDataException("HexString is not valid for conversion to bytes"); } } } public class Tally<T> : Dictionary<T, int> { public new int this[T key] { get { if (!TryGetValue(key, out var value)) { return 0; } return value; } set { base[key] = value; } } public HashSet<T> Diff(Tally<T>? other) { HashSet<T> hashSet; if (other == null) { hashSet = new HashSet<T>(); { foreach (T key in base.Keys) { hashSet.Add(key); } return hashSet; } } IEnumerable<KeyValuePair<T, int>> first = this.Except<KeyValuePair<T, int>>(other); IEnumerable<KeyValuePair<T, int>> second = other.Except<KeyValuePair<T, int>>(this); hashSet = new HashSet<T>(); foreach (T item in from item in first.Union(second) select item.Key) { hashSet.Add(item); } return hashSet; } public IEnumerable<(T Key, int Amount)> Sorted() { return this.OrderByDescending(delegate(KeyValuePair<T, int> pair) { KeyValuePair<T, int> keyValuePair2 = pair; return keyValuePair2.Value; }).Select(delegate(KeyValuePair<T, int> pair) { KeyValuePair<T, int> keyValuePair = pair; T key = keyValuePair.Key; keyValuePair = pair; return (key, keyValuePair.Value); }); } } public static class TallyExt { public static Tally<T> SumItems<T>(this Inventory inv, Func<ItemData, T> callback) { Tally<T> tally = new Tally<T>(); foreach (ItemData allItem in inv.GetAllItems()) { tally[callback(allItem)] += allItem.m_stack; } return tally; } public static Tally<string> SumItemsByName(this Inventory inv) { return inv.SumItems((ItemData item) => item.GetName()); } public static Tally<string> SumItemsByPrefabName(this Inventory inv) { return inv.SumItems((ItemData item) => item.GetPrefabName()); } } public static class TerminalCommand { private static readonly List<string> Commands = new List<string>(); public static ConsoleCommand Create(string name, string description, bool isCheat, Action<string[]> action) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown Action<string[]> action2 = action; string text = ((BaseUnityPlugin)ZenPlugin.Instance).Info.Metadata.Name + "_" + name; Commands.Add(text); Log.Info("Terminal command added: " + text, "Create", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\TerminalCommand.cs"); return new ConsoleCommand(text, description, (ConsoleEvent)delegate(ConsoleEventArgs args) { action2(args.Args); }, isCheat, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } internal static void Cleanup() { foreach (string command in Commands) { Terminal.commands.Remove(command.ToLower()); } Commands.Clear(); } } public static class UIColor { public struct ZColor { public string Hex { get; } public Color Color { get; } public ZColor(Color32 c) : this(c.r, c.g, c.b, c.a) { }//IL_0001: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) public ZColor(byte r, byte g, byte b, byte a) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Color = Color32.op_Implicit(new Color32(r, g, b, a)); Hex = ColorUtility.ToHtmlStringRGBA(Color); } public override string ToString() { return "#" + Hex; } } public static readonly ZColor Gray = new ZColor(170, 170, 170, byte.MaxValue); public static readonly ZColor Teal = new ZColor(170, byte.MaxValue, 170, byte.MaxValue); public static readonly ZColor Red = new ZColor(204, 0, 0, byte.MaxValue); public static readonly ZColor Purple = new ZColor(147, 49, 189, byte.MaxValue); public static readonly ZColor Yellow = new ZColor(Color32.op_Implicit(Color.yellow)); public static readonly ZColor Orange = new ZColor(byte.MaxValue, 165, 0, byte.MaxValue); public static readonly ZColor LightYellow = new ZColor(byte.MaxValue, byte.MaxValue, 170, byte.MaxValue); public static readonly ZColor MinorInfo = Gray; public static readonly ZColor MajorInfo = Orange; } public static class UI { public static readonly string PromptUseItem = Prompt("1-8"); public static readonly string PromptInteract = Prompt("$KEY_Use"); public static readonly string PromptInteractAlt = Prompt($"$KEY_{ControlInputs.InteractAlt}"); public static bool IsBuildModeActive { get { if (!Hud.IsPieceSelectionVisible()) { if (Object.op_Implicit((Object)(object)Hud.instance) && Object.op_Implicit((Object)(object)Hud.instance.m_buildHud)) { return Hud.instance.m_buildHud.activeSelf; } return false; } return true; } } public static bool IsOpen { get { if (!Object.op_Implicit((Object)(object)Game.instance) || !Object.op_Implicit((Object)(object)GameCamera.instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return true; } if (((Character)Player.m_localPlayer).TakeInput()) { return IsBuildModeActive; } return true; } } public static string Prompt(string text) { return "[<color=yellow><b>" + text + "</b></color>]"; } public static TimeSpan RealToGameTime(float seconds) { float num = seconds / (float)EnvMan.instance.m_dayLengthSec; return TimeSpan.FromDays((num <= 0f) ? 0f : (num + 0.51f)); } public static string RemainingTimeText(float seconds, float secPerFuel = -1f) { bool num = secPerFuel > (float)EnvMan.instance.m_dayLengthSec; TimeSpan timeSpan = (num ? RealToGameTime(seconds) : TimeSpan.FromSeconds(seconds)); string result = "None"; if (num) { if (timeSpan.Days > 0) { result = $"{timeSpan.Days} day" + ((timeSpan.Days > 1) ? "s" : ""); } else if (timeSpan.TotalSeconds > 0.0) { result = "Less than a day"; } } else { double totalMinutes = timeSpan.TotalMinutes; if (totalMinutes > 0.0 && totalMinutes <= 1.0) { result = "Less than a minute"; } else { totalMinutes = timeSpan.TotalMinutes; if (totalMinutes > 1.0 && totalMinutes < 60.0) { result = $"{timeSpan.Minutes + 1} minutes"; } } } return result; } public static void HideStackAllButton() { Log.Info("Hiding StackAll button", "HideStackAllButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\UI.cs"); ((Component)InventoryGui.instance.m_stackAllButton).gameObject.SetActive(false); ((MonoBehaviour)ZenPlugin.Instance).StartCoroutine(Restore()); static IEnumerator Restore() { do { Log.Info("Restoring StackAll button visibility", "HideStackAllButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\UI.cs"); yield return (object)new WaitWhile((Func<bool>)InventoryGui.IsVisible); yield return (object)new WaitForSeconds(0.5f); } while (InventoryGui.IsVisible()); ((Component)InventoryGui.instance.m_stackAllButton).gameObject.SetActive(true); } } public static Material AddValheimIconShadow(this Image image) { return ((Graphic)image).material = ((Graphic)Hud.instance.m_buildIcon).material; } public static Outline AddOutline(this GameObject gameObject) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return gameObject.AddOutline(1f, Color.black); } public static Outline AddOutline(this GameObject gameObject, float thickness, Color effectColor = default(Color)) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Outline orAddComponent = ExposedGameObjectExtension.GetOrAddComponent<Outline>(gameObject); ((Shadow)orAddComponent).effectDistance = Vector2.one * thickness; ((Shadow)orAddComponent).effectColor = ((effectColor == default(Color)) ? Color.black : effectColor); return orAddComponent; } } [BepInIncompatibility("org.bepinex.plugins.valheim_plus")] internal abstract class ZenPlugin : BaseUnityPlugin { private const string BitcoinAddr = "bc1q34lrc82dp73jhv9ylefz0gvmeqfn96e938p4pf"; private const string HomeURL = "https://github.com/ZenDragonX/ZenMods_Valheim"; private static readonly Harmony H = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); internal static ConfigEntry<bool> IsLogEnabled = null; private static bool _loadedOnce; private bool _initialized; public static ZenPlugin Instance { get; private set; } = null; internal static ManualLogSource InstanceLogger => ((BaseUnityPlugin)Instance).Logger; public static bool Initialized { get { if (Object.op_Implicit((Object)(object)Instance) && Instance._initialized) { return Instance.IsSysReady; } return false; } } protected virtual GameVersion? ValheimVersion => null; protected virtual bool RunOnServer => false; protected virtual bool IsSysReady { get { if (!RunOnServer || !Object.op_Implicit((Object)(object)ZoneSystem.instance) || !Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated()) { if (Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)Hud.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront); } return false; } return true; } } public event Action? RegisterInputs; public event Action? RegisterCraftingItems; public event Action<string>? LanguageChanged; protected abstract void Setup(); protected abstract void TitleScene(bool isFirstBoot); protected abstract void WorldStart(); protected abstract void Shutdown(); protected ZenPlugin() { Game.isModded = true; if (Object.op_Implicit((Object)(object)Instance)) { throw new Exception($"There can be only one instance of {((object)this).GetType()}"); } Instance = this; } private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0048: Unknown result type (might be due to invalid IL or missing references) if (ValheimVersion.HasValue) { GameVersion? valheimVersion = ValheimVersion; GameVersion currentVersion = Version.CurrentVersion; if (!valheimVersion.HasValue || valheimVersion.GetValueOrDefault() != currentVersion) { Log.Error($"Valheim version mismatch. Required: {ValheimVersion} Current: {Version.CurrentVersion}", "Awake", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs"); AbortInit(); return; } } Config.DefineConfig(isAdmin: true, "_Author", "Donations Welcome", defaultValue: true, null, "Like My Mods?\nBitcoin: bc1q34lrc82dp73jhv9ylefz0gvmeqfn96e938p4pf\nWebsite: https://github.com/ZenDragonX/ZenMods_Valheim"); IsLogEnabled = Config.DefineConfig(isAdmin: false, "_Debug", "Enable Logging", defaultValue: false); ZInput.OnInputLayoutChanged += OnInputLayoutChanged; SceneManager.sceneLoaded += OnSceneLoaded; PrefabManager.OnVanillaPrefabsAvailable += CraftingReady; Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(OnLanguageChange)); Setup(); PreInit(); void CraftingReady() { this.RegisterCraftingItems?.Invoke(); PrefabManager.OnVanillaPrefabsAvailable -= CraftingReady; } } private void OnLanguageChange() { string @string = PlayerPrefs.GetString("language", "English"); this.LanguageChanged?.Invoke(@string); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (((Scene)(ref scene)).name == "start") { Config.StringList.AccessCount.Clear(); KeyHint.RemoveAll(); TitleScene(!_initialized); PreInit(); } } private void OnInputLayoutChanged() { ControlSetup.Init(); this.RegisterInputs?.Invoke(); } private void PreInit() { _initialized = false; ((MonoBehaviour)this).StopAllCoroutines(); ((MonoBehaviour)this).CancelInvoke("CheckInit"); ((MonoBehaviour)this).InvokeRepeating("CheckInit", 1f, 1f); } private void OnDestroy() { Log.Info("Cleanup", "OnDestroy", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs"); GUIManager.BlockInput(false); SceneManager.sceneLoaded -= OnSceneLoaded; ZInput.OnInputLayoutChanged -= OnInputLayoutChanged; Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(OnLanguageChange)); Shutdown(); ((MonoBehaviour)this).StopAllCoroutines(); ActionString.RemoveAll(); KeyHint.RemoveAll(); Cleanup.External(); TerminalCommand.Cleanup(); H.UnpatchSelf(); Instance = null; } private void CheckInit() { Log.Debug("CheckInit", "CheckInit", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs"); if (!IsSysReady || !Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return; } if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated() && !RunOnServer) { Log.Info("Abort init. Running on server.", "CheckInit", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs"); AbortInit(); return; } ((MonoBehaviour)this).CancelInvoke("CheckInit"); if (!_loadedOnce) { OnLanguageChange(); OnInputLayoutChanged(); } Log.Info("Init complete - Game Start", "CheckInit", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\ZenPlugin.cs"); WorldStart(); _initialized = true; _loadedOnce = true; } private void AbortInit() { ((MonoBehaviour)this).CancelInvoke("CheckInit"); H.UnpatchSelf(); } } } namespace ZenModLib.Controls { public class ActionString { private enum InputMode { Keyboard, Gamepad } private static readonly string PluginName = ((BaseUnityPlugin)ZenPlugin.Instance).Info.Metadata.Name; private static readonly HashSet<ActionString> RegisteredActions = new HashSet<ActionString>(); public readonly string NameShort; public readonly string Name; public readonly string Label; public ButtonDef? AliasKBM { get; private set; } public ButtonDef? AliasJoy { get; private set; } public static implicit operator string(ActionString input) { return input.ToString(); } public ActionString(string actionName, string label, bool safeNamespace = true) { if (Utility.IsNullOrWhiteSpace(actionName)) { throw new Exception("ActionString can not be empty or null."); } NameShort = actionName; Name = (safeNamespace ? (Regex.Replace(PluginName, "[^\\w]", "_") + "_" + actionName) : actionName); Label = Localization.instance.Localize(label); UpdateTranslationLabels(); RegisteredActions.Add(this); } private void UpdateTranslationLabels() { if (!Utility.IsNullOrWhiteSpace(Label)) { Localization.instance.AddWord(Name, Label); Localization.instance.AddWord("settings_" + Name.ToLower(), Label); } } private static void AddButton(string name, string path, bool altKey, bool showHints, bool rebindable, float repeatDelay, float repeatInterval) { if (ZInput.instance.m_buttons.TryGetValue(name, out var value)) { Log.Info("Skip existing button: " + value.GetActionPath(true) + "\t" + value.Name, "AddButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\ActionString.cs"); return; } if (rebindable && (path.StartsWith("<Keyboard>") || path.StartsWith("<Mouse>"))) { string @string = PlayerPrefs.GetString("kbmBinding_" + name); if (!Utility.IsNullOrWhiteSpace(@string)) { path = @string; } } Log.Info("Add Button: " + path + "\t" + name, "AddButton", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\ActionString.cs"); ZInput.instance.AddButton(name, path, altKey, showHints, rebindable, repeatDelay, repeatInterval); } public void AddButton(GamepadInput input, bool altKey = false, bool showHints = false, bool rebindable = false, float repeatDelay = 0f, float repeatInterval = 0f) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) AddButton("Joy" + Name, input.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval); } public void AddButton(MouseButton input, bool altKey = false, bool showHints = false, bool rebindable = false, float repeatDelay = 0f, float repeatInterval = 0f) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) AddButton(Name, input.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval); } public void AddButton(KeyCode input, bool altKey = false, bool showHints = false, bool rebindable = false, float repeatDelay = 0f, float repeatInterval = 0f) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) AddButton(Name, input.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval); } public void AddButton(Key input, bool altKey = false, bool showHints = false, bool rebindable = false, float repeatDelay = 0f, float repeatInterval = 0f) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) AddButton(Name, input.Path(), altKey, showHints, rebindable, repeatDelay, repeatInterval); } public void Alias(string existingName) { ButtonDef buttonDef = ZInput.instance.GetButtonDef(existingName); string actionPath = buttonDef.GetActionPath(true); if (actionPath.StartsWith("<Gamepad>")) { AliasJoy = buttonDef; } else if (actionPath.StartsWith("<Keyboard>") || actionPath.StartsWith("<Mouse>")) { AliasKBM = buttonDef; } Log.Info("Alias: " + buttonDef.GetActionPath(true) + "\t" + existingName + " -> " + Name, "Alias", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\ActionString.cs"); } public override string ToString() { if (ZInput.IsGamepadActive()) { if (AliasJoy == null) { return "Joy" + Name; } return AliasJoy.Name; } if (AliasKBM == null) { return Name; } return AliasKBM.Name; } public void RemoveButtons() { ZInput.instance.RemoveButton(Name); ZInput.instance.RemoveButton("Joy" + Name); } internal static void RemoveAll() { foreach (ActionString registeredAction in RegisteredActions) { registeredAction.RemoveButtons(); } } } public static class ControlInputs { public static readonly ActionString InteractAlt = new ActionString("ZenModLib_InteractAltButton", "Alt interact", safeNamespace: false); public static string JoyAlt { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)ZInput.InputLayout != 1) { return JoyTrigger; } return JoyBumper; } } public static string JoyTrigger { get { if (!ZInput.SwapTriggers) { return "JoyLTrigger"; } return "JoyRTrigger"; } } public static string JoyBumper { get { if (!ZInput.SwapTriggers) { return "JoyLBumper"; } return "JoyRBumper"; } } public static GamepadInput TriggerSwappedL { get { if (ZInput.SwapTriggers) { return (GamepadInput)18; } return (GamepadInput)17; } } public static GamepadInput BumperSwappedL { get { if (ZInput.SwapTriggers) { return (GamepadInput)16; } return (GamepadInput)15; } } public static GamepadInput TriggerSwappedR { get { if (ZInput.SwapTriggers) { return (GamepadInput)17; } return (GamepadInput)18; } } public static GamepadInput BumperSwappedR { get { if (ZInput.SwapTriggers) { return (GamepadInput)15; } return (GamepadInput)16; } } } internal static class ControlSetup { private static readonly List<MethodInfo> Success = new List<MethodInfo>(); public static void Init() { Apply(GamepadFix.Remap_BasicDefaults); Apply(InteractAltButton.CreateInteractAlt); } private static void Apply(Func<bool> fix) { if (fix()) { Log.Message("Success: " + fix.Method.Name, "Apply", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\ControlSetup.cs"); Success.Add(fix.Method); } } internal static bool IsApplied(Func<bool> method) { return Success.Contains(method.Method); } } [HarmonyPatch] internal static class GamepadFix { internal static bool Remap_BasicDefaults() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Invalid comparison between Unknown and I4 //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) bool? showHints; if ((int)ZInput.InputLayout == 0) { if (!ZInput.instance.GetButtonDef("JoyGP").RemapTo((GamepadInput)8, true)) { return false; } } else { ButtonDef buttonDef = ZInput.instance.GetButtonDef("JoyAltPlace"); showHints = false; if (!buttonDef.RemapTo((GamepadInput)19, null, showHints)) { return false; } GamepadInput newInput = (((int)ZInput.InputLayout == 1) ? ControlInputs.TriggerSwappedL : ControlInputs.BumperSwappedL); if (!ZInput.instance.GetButtonDef("JoyCrouch").RemapTo(newInput, false)) { return false; } } if (!ZInput.instance.GetButtonDef("JoyHide").RemapTo((GamepadInput)3, false)) { return false; } if (!ZInput.instance.GetButtonDef("JoySit").RemapTo((GamepadInput)19, false)) { return false; } if (!ZInput.instance.GetButtonDef("JoyMap").RemapTo((GamepadInput)19, true)) { return false; } ButtonDef buttonDef2 = ZInput.instance.GetButtonDef("JoyChat"); showHints = false; if (!buttonDef2.RemapTo((GamepadInput)0, null, showHints)) { return false; } return true; } [HarmonyTranspiler] [HarmonyPatch(typeof(Minimap), "Update")] private static IEnumerable<CodeInstruction> RemapJoyMap_Minimap_Update_Transpile(IEnumerable<CodeInstruction> codes) { bool alreadyPatched = false; foreach (CodeInstruction code in codes) { if (CodeInstructionExtensions.Is(code, OpCodes.Ldstr, (object)"JoyMap_DISABLED")) { alreadyPatched = true; } if (code.opcode == OpCodes.Ret && !alreadyPatched) { yield return CodeInstruction.Call(typeof(GamepadFix), "RemapJoyMap_Minimap", (Type[])null, (Type[])null); } if (CodeInstructionExtensions.Is(code, OpCodes.Ldstr, (object)"JoyMap")) { yield return new CodeInstruction(OpCodes.Ldstr, (object)"JoyMap_DISABLED"); } else { yield return code; } } } private static void RemapJoyMap_Minimap() { if (ZInput.IsGamepadActive() && !UI.IsOpen && ZInput.GetButtonDown("JoyMap") && ZInput.GetButton(ControlInputs.JoyAlt)) { ToggleMap(); } static void ToggleMap() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected I4, but got Unknown Minimap instance = Minimap.instance; MapMode mode = instance.m_mode; switch ((int)mode) { case 0: instance.SetMapMode((MapMode)1); break; case 1: instance.SetMapMode((MapMode)2); break; case 2: instance.SetMapMode((MapMode)1); break; } } } [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "Update")] private static IEnumerable<CodeInstruction> JoyAltHide_Player_Update_Transpile(IEnumerable<CodeInstruction> codes) { MethodInfo methodInfo = AccessTools.Method(typeof(Character), "InPlaceMode", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(GamepadFix), "Character_InPlaceMode_Intercept", (Type[])null, (Type[])null); return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2); } private static bool Character_InPlaceMode_Intercept(Character _) { if (!Hud.IsPieceSelectionVisible() && !InventoryGui.IsVisible()) { return Minimap.IsOpen(); } return true; } [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "Update")] private static IEnumerable<CodeInstruction> JoyAltPlace_Player_Update_Transpile(IEnumerable<CodeInstruction> codes) { MethodInfo methodInfo = AccessTools.Method(typeof(ZInput), "GetButton", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(ZInput), "GetButtonDown", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeof(ZInput), "GetButtonUp", (Type[])null, (Type[])null); MethodInfo methodInfo4 = AccessTools.Method(typeof(GamepadFix), "JoyAltPlace_GetButton", (Type[])null, (Type[])null); MethodInfo methodInfo5 = AccessTools.Method(typeof(GamepadFix), "JoyAltPlace_GetButtonDown", (Type[])null, (Type[])null); MethodInfo methodInfo6 = AccessTools.Method(typeof(GamepadFix), "JoyAltPlace_GetButtonUp", (Type[])null, (Type[])null); codes = Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo4); codes = Transpilers.MethodReplacer(codes, (MethodBase)methodInfo2, (MethodBase)methodInfo5); codes = Transpilers.MethodReplacer(codes, (MethodBase)methodInfo3, (MethodBase)methodInfo6); return codes; } private static bool JoyAltPlace_GetButton(string name) { return JoyAltPlace_Intercept(name, (Func<string, bool>)ZInput.GetButton); } private static bool JoyAltPlace_GetButtonDown(string name) { return JoyAltPlace_Intercept(name, (Func<string, bool>)ZInput.GetButtonDown); } private static bool JoyAltPlace_GetButtonUp(string name) { return JoyAltPlace_Intercept(name, (Func<string, bool>)ZInput.GetButtonUp); } private static bool JoyAltPlace_Intercept(string name, Func<string, bool> getBtnFunc) { if (name != "JoyAltPlace") { return getBtnFunc(name); } if (UI.IsBuildModeActive) { return getBtnFunc(name); } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(InventoryGui), "Show")] private static void Remap_BasicDefaults_InventoryGui_Show(ref bool __runOriginal) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (ControlSetup.IsApplied(Remap_BasicDefaults) && ZInput.IsGamepadActive() && (int)ZInput.InputLayout == 0) { bool button = ZInput.GetButton(ControlInputs.JoyAlt); if (ZInput.GetButton("JoyGP") && button) { __runOriginal = false; Player.m_localPlayer.StartGuardianPower(); } } } } [HarmonyPatch] internal static class InteractAltButton { public const string Name = "ZenModLib_InteractAltButton"; public const string Label = "Alt interact"; private static float _lastInteractTime; internal static bool CreateInteractAlt() { ActionString actionString = new ActionString("Initialized_CreateInteractAlt", string.Empty, safeNamespace: false); if (ZInput.instance.GetButtonDef(actionString.Name) != null) { return false; } actionString.AddButton((KeyCode)0); ZenPlugin.Instance.RegisterInputs += delegate { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Log.Message("Register Inputs: InteractAlt", "CreateInteractAlt", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Controls\\InteractAltButton.cs"); ControlInputs.InteractAlt.RemoveButtons(); GamepadInput input = (((int)ZInput.InputLayout == 1) ? ControlInputs.TriggerSwappedL : ControlInputs.BumperSwappedL); ControlInputs.InteractAlt.AddButton(input); ButtonDef buttonDef = ZInput.instance.GetButtonDef("AutoRun"); if (buttonDef.GetActionPath(true).ToUpper().EndsWith("Q")) { buttonDef.RemapTo((KeyCode)92); } ControlInputs.InteractAlt.AddButton((KeyCode)113); }; return true; } [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "SetControls")] private static IEnumerable<CodeInstruction> Player_SetControls_Transpile(IEnumerable<CodeInstruction> codes) { MethodInfo methodInfo = AccessTools.Method(typeof(Character), "SetCrouch", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(InteractAltButton), "SetCrouch_Intercept", (Type[])null, (Type[])null); return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2); } private static void SetCrouch_Intercept(Player player, bool crouch) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (crouch && ZInput.IsGamepadActive() && (int)ZInput.InputLayout != 0) { if (player.IsHoveringValidObject()) { crouch = false; } else if (Time.time < _lastInteractTime + 0.5f) { crouch = false; } } ((Character)player).SetCrouch(crouch); } [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "Interact")] private static IEnumerable<CodeInstruction> Player_Interact_Transpile(IEnumerable<CodeInstruction> codes) { MethodInfo methodInfo = AccessTools.Method(typeof(Interactable), "Interact", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(InteractAltButton), "Interact_Intercept", (Type[])null, (Type[])null); return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2); } private static bool Interact_Intercept(Interactable self, Humanoid user, bool hold, bool alt) { if (alt) { _lastInteractTime = Time.time; } return self.Interact(user, hold, alt); } [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "Update")] private static IEnumerable<CodeInstruction> Player_Update_Transpile_HandleAltInteract(IEnumerable<CodeInstruction> codes) { MethodInfo methodInfo = AccessTools.Method(typeof(Player), "UpdateStats", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(InteractAltButton), "Player_UpdateStats_Intercept", (Type[])null, (Type[])null); return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2); } private static void Player_UpdateStats_Intercept(Player player) { player.UpdateStats(); CheckForInteraction(player); } private static void CheckForInteraction(Player player) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!UI.IsOpen && !Hud.InRadial() && !((Character)player).IsTeleporting() && !((Character)player).IsDead() && !((Character)player).InDodge() && !((Character)player).IsRunning() && !(((Character)player).GetMoveDir() != Vector3.zero) && player.IsHoveringValidObject()) { if (ZInput.GetButtonDown((string)ControlInputs.InteractAlt)) { player.Interact(player.m_hovering, false, true); } else if (ZInput.GetButton((string)ControlInputs.InteractAlt) && ZInput.GetButtonPressedTimer((string)ControlInputs.InteractAlt) > 0.3f) { player.Interact(player.m_hovering, true, true); } } } private static bool IsHoveringValidObject(this Player player) { if (!Object.op_Implicit((Object)(object)player.m_hovering) || Utility.IsNullOrWhiteSpace(((TMP_Text)Hud.instance.m_hoverName).text)) { return false; } if (!((TMP_Text)Hud.instance.m_hoverName).text.Contains(UI.PromptInteractAlt.Localize().GlyphFix())) { return false; } return true; } public static string InsertButtonText(string hoverText, string label) { string pattern = "^(" + UI.PromptInteract.RegexPattern() + ".*)$"; string text = UI.PromptInteractAlt + " " + label; return Regex.Replace(hoverText, pattern, "$1\n" + text, RegexOptions.Multiline); } } [HarmonyPatch] public static class InteractAlt_FixVanilla { [HarmonyTranspiler] [HarmonyPatch(typeof(Tameable), "GetHoverText")] private static IEnumerable<CodeInstruction> Tameable_GetHoverText_Transpile(IEnumerable<CodeInstruction> codes) { return Transpilers.Manipulator(Transpilers.Manipulator(codes, (Func<CodeInstruction, bool>)((CodeInstruction ci) => CodeInstructionExtensions.Is(ci, OpCodes.Ldstr, (object)"\n[<color=yellow><b>$KEY_AltKeys + $KEY_Use</b></color>] $hud_rename")), (Action<CodeInstruction>)delegate(CodeInstruction ci) { ci.operand = "\n[<color=yellow><b>$KEY_ZenModLib_InteractAltButton</b></color>] $hud_rename"; }), (Func<CodeInstruction, bool>)((CodeInstruction ci) => CodeInstructionExtensions.Is(ci, OpCodes.Ldstr, (object)"\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $hud_rename")), (Action<CodeInstruction>)delegate(CodeInstruction ci) { ci.operand = "\n[<color=yellow><b>$KEY_ZenModLib_InteractAltButton</b></color>] $hud_rename"; }); } } } namespace ZenModLib.Compatibility { [HarmonyPatch] internal static class MultiUserChest { [AttributeUsage(AttributeTargets.Class)] internal sealed class DisableAttribute : Attribute { public DisableAttribute(params Type[] types) { _disabledTypes = types; } } private static Type[] _disabledTypes = Array.Empty<Type>(); [HarmonyBefore(new string[] { "com.maxsch.valheim.MultiUserChest" })] [HarmonyPostfix] [HarmonyPatch(typeof(Container), "Awake")] private static void Container_Awake(Container __instance) { Type[] disabledTypes = _disabledTypes; foreach (Type type in disabledTypes) { if (Object.op_Implicit((Object)(object)((Component)__instance).GetComponent(type))) { Disable(__instance); } } } internal static void Disable(Container container) { if (container.m_nview.IsOwner()) { Log.Info("Disable Multi User Chest", "Disable", "C:\\Projects\\ValheimDev\\ModDev\\ZenModLib\\ZenModLib\\Compatibility\\MultiUserChest.cs"); ZDO zDO = container.m_nview.GetZDO(); if (!zDO.GetBool("MUC_Ignore", false)) { zDO.Set("MUC_Ignore", true); } } } } } namespace ZenRedecorate { public static class Configs { public static ConfigEntry<bool> IsEncumberedWhenMovingPiece; public static ConfigEntry<bool> IsProvidesSupportImmovable; public static ConfigEntry<bool> ProvidesSupportWarning; public static ConfigEntry<KeyCode> InputHoldKey; public static ConfigEntry<KeyCode> InputPickup; public static ConfigEntry<float> MaxCarryRange; public static ConfigEntry<Config.StringList> AllowedPrefabs; public static ConfigEntry<Config.StringList> DeniedPrefabs; internal static void Init() { IsEncumberedWhenMovingPiece = Config.DefineConfig(isAdmin: true, "General", "Encumbered When Redecorating", defaultValue: true, null, "Player is encumbered when moving things.\nThis protects against making it too easy to transport chests full of stuff over long distances.\nThat's what carts are for."); IsProvidesSupportImmovable = Config.DefineConfig(isAdmin: true, "General", "Provides Support Is Immovable", defaultValue: true, null, "Can not move anything that provides support, except furniture."); ProvidesSupportWarning = Config.DefineConfig(isAdmin: false, "General", "Provides Support Warning", defaultValue: false, null, "Display a warning before trying to move an object that provides support. This setting ignores the IsProvidesSupportImmovable settings because things like beds and tables also provide support as they are furniture."); AllowedPrefabs = Config.DefineConfig(isAdmin: true, "General", "Allowed Prefabs", new Config.StringList { "wood_fine_stack", "blackwood_stack", "bone_stack", "piece_beehive" }, null, "These prefabs are always allowed to be moved."); DeniedPrefabs = Config.DefineConfig(isAdmin: true, "General", "Denied Prefabs", new Config.StringList { "fire_pit", "bonfire", "hearth", "windmill" }, null, "These prefabs are never allowed to be moved."); MaxCarryRange = Config.DefineConfig(isAdmin: true, "General", "Max Carry Range", 50f, null, "Maximum distance that a piece can be carried before automatic abort."); InputHoldKey = Config.DefineConfig<KeyCode>(isAdmin: true, "Input", "Mode Select Modifier Key", (KeyCode)306, null, "Modifier Key to hold down to switch into move mode."); InputPickup = Config.DefineConfig<KeyCode>(isAdmin: true, "Input", "Pickup", (KeyCode)323, null, "Button to press to pickup."); } } [HarmonyPatch] internal static class Inputs { public static readonly ActionString Pickup = new ActionString("Pickup", "$inventory_pickup"); public static readonly ActionString HoldKey = new ActionString("Modifier", "$inventory_move"); internal static void RegisterInputs() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Pickup.AddButton((GamepadInput)7, altKey: false, showHints: true); Pickup.AddButton(Configs.InputPickup.Value); HoldKey.AddButton(Configs.InputHoldKey.Value); } internal static void CreateKeyHints() { KeyHint.Create(HintType.Build, Pickup, 1); KeyHint.Create(HintType.Build, HoldKey, 1); KeyHint.UpdateBuildHints += UpdateHints; } private static void UpdateHints() { if (Hud.IsPieceSelectionVisible()) { KeyHint.SetVisible(HoldKey, isVisible: false); KeyHint.SetVisible(Pickup, isVisible: false); } else { KeyHint.SetVisible(HoldKey, !ZInput.IsGamepadActive() && !Redecorate.IsMoving && !ZInput.GetButton((string)HoldKey)); KeyHint.SetVisible(Pickup, (ZInput.IsGamepadActive() && !Redecorate.IsMoving) || (!ZInput.IsGamepadActive() && !Redecorate.IsMoving && ZInput.GetButton((string)HoldKey))); } KeyHint.SetVisible("Place", !ZInput.GetButton((string)HoldKey) || Redecorate.IsMoving); KeyHint.SetVisible("BuildMenu", !Redecorate.IsMoving); KeyHint.SetVisible("Copy", !Redecorate.IsMoving); } } [HarmonyPatch] public static class Patch { [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] private static class Player_HaveRequirements { [UsedImplicitly] private static void Prefix(Piece piece, ref Requirement[] __state) { if (Redecorate.IsMoving) { __state = piece.m_resources; piece.m_resources = Array.Empty<Requirement>(); } } [UsedImplicitly] private static void Postfix(Piece piece, Requirement[] __state) { if (Redecorate.IsMoving) { piece.m_resources = __state; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "IsEncumbered")] private static void Player_IsEncumbered(Player __instance, ref bool __result) { if (!((Object)(object)Player.m_localPlayer != (Object)(object)__instance) && Redecorate.IsMoving && Configs.IsEncumberedWhenMovingPiece.Value) { __result = true; } } [HarmonyPrefix] [HarmonyPatch(typeof(StatusEffect), "Setup")] private static void StatusEffect_Encumbered_Setup(StatusEffect __instance, ref bool __runOriginal, Character character) { if (__instance.NameHash() == SEMan.s_statusEffectEncumbered && Redecorate.IsMoving && !((Object)(object)character != (Object)(object)Player.m_localPlayer)) { __instance.m_startMessage = string.Empty; } } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "SetupPieceInfo")] private static void Hud_SetupPieceInfo(Hud __instance, Piece piece) { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) if (Redecorate.IsMoving) { GameObject[] requirementItems = __instance.m_requirementItems; for (int i = 0; i < requirementItems.Length; i++) { requirementItems[i].SetActive(false); } __instance.m_requirementItems[0].SetActive(true); ((Component)__instance.m_requirementItems[0].transform.Find("res_icon")).GetComponent<Image>().sprite = Redecorate.EncumberedIcon; ((Component)__instance.m_requirementItems[0].transform.Find("res_name")).GetComponent<TMP_Text>().text = ""; ((Component)__instance.m_requirementItems[0].transform.Find("res_amount")).GetComponent<TMP_Text>().text = ""; if (Object.op_Implicit((Object)(object)piece.m_craftingStation)) { GameObject val = __instance.m_requirementItems[1]; GameObject val2 = __instance.m_requirementItems[piece.m_resources.Length]; Image component = ((Component)val.transform.Find("res_icon")).GetComponent<Image>(); Image component2 = ((Component)val2.transform.Find("res_icon")).GetComponent<Image>(); component.sprite = component2.sprite; ((Graphic)component).color = ((Graphic)component2).color; TMP_Text component3 = ((Component)val.transform.Find("res_name")).GetComponent<TMP_Text>(); TMP_Text component4 = ((Component)val2.transform.Find("res_name")).GetComponent<TMP_Text>(); component3.text = component4.text; ((Graphic)component3).color = ((Graphic)component4).color; TMP_Text component5 = ((Component)val.transform.Find("res_amount")).GetComponent<TMP_Text>(); TMP_Text component6 = ((Component)val2.transform.Find("res_amount")).GetComponent<TMP_Text>(); component5.text = component6.text; ((Graphic)component5).color = ((Graphic)component6).color; val.GetComponent<UITooltip>().m_text = val2.GetComponent<UITooltip>().m_text; val.SetActive(true); } } else if (Redecorate.IsPickupModifierPressed()) { __instance.m_buildIcon.sprite = Redecorate.EncumberedIcon; __instance.m_buildSelection.text = Localization.instance.Localize("$inventory_move"); __instance.m_pieceDescription.text = ""; GameObject[] requirementItems = __instance.m_requirementItems; for (int i = 0; i < requirementItems.Length; i++) { requirementItems[i].SetActive(false); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "Damage")] private static void Character_Damage(Character __instance) { if (!((Object)(object)Player.m_localPlayer != (Object)(object)__instance) && Redecorate.IsMoving) { Redecorate.AbortMove(); ((Humanoid)Player.m_localPlayer).HideHandItems(false, true); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "TeleportTo")] private static void Player_TeleportTo(Player __instance) { if ((Object)(object)Player.m_localPlayer == (Object)(object)__instance && Redecorate.IsMoving) { Redecorate.AbortMove(); } } [HarmonyPrefix] [HarmonyPatch(typeof(Hud), "TogglePieceSelection")] private static void Hud_TogglePieceSelection(Hud __instance, ref bool __runOriginal) { if (Redecorate.IsMoving) { __runOriginal = false; Redecorate.AbortMove(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "UpdateBuild")] private static void Hud_UpdateBuild(Hud __instance) { if ((!Object.op_Implicit((Object)(object)__instance.m_buildHud) || !__instance.m_buildHud.activeSelf) && Redecorate.IsMoving) { Redecorate.AbortMove(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "UpdateCrosshair")] private static void Hud_UpdateCrosshair(Hud __instance) { if (!Redecorate.IsMoving && Redecorate.IsPickupModifierPressed()) { ((Component)__instance.m_pieceHealthRoot).gameObject.SetActive(false); } } [HarmonyPrefix] [HarmonyPatch(typeof(PieceTable), "GetSelectedPiece")] private static void PieceTable_GetSelectedPiece(PieceTable __instance, ref bool __runOriginal, ref Piece __result) { if (Redecorate.IsMoving) { __runOriginal = false; __result = Redecorate.PlacementGhostPiece; } else if (Object.op_Implicit((Object)(object)Redecorate.CachedBuildPiece)) { __runOriginal = false; __result = Redecorate.CachedBuildPiece; } } [HarmonyPrefix] [HarmonyPatch(typeof(PieceTable), "GetSelectedPrefab")] private static void PieceTable_GetSelectedPrefab(PieceTable __instance, ref bool __runOriginal, ref GameObject __result) { if (Redecorate.IsMoving) { __runOriginal = false; __result = Redecorate.GetSelected(); } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "TryPlacePiece")] private static void Player_TryPlacePiece(Player __instance, ref bool __runOriginal, ref bool __result) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (Redecorate.IsMoving && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { __runOriginal = false; __result = false; __instance.UpdatePlacementGhost(true); if ((int)__instance.m_placementStatus == 0) { Redecorate.PlacePiece(); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "CopyPiece")] private static void Player_CopyPiece(Player __instance, ref bool __runOriginal, ref bool __result) { if (Redecorate.IsMoving) { __runOriginal = false; __result = false; } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "AutoPickup")] private static void Player_AutoPickup(ref bool __runOriginal) { if (Redecorate.IsMoving) { __runOriginal = false; } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "UpdateAvailablePiecesList")] private static void Player_UpdateAvailablePiecesList(Player __instance) { Log.Debug("Build pieces list updated", "Player_UpdateAvailablePiecesList", "C:\\Projects\\ValheimDev\\ModDev\\ZenRedecorate\\ZenRedecorate\\Patch.cs"); if (Redecorate.IsMoving) { Redecorate.AbortMove(); } } [HarmonyPostfix] [Harm