Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Infinite Torch v1.0.0
plugins/InfiniteTorch.dll
Decompiled a week agousing System; using System.Collections; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("BenjSammy")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Unlimited durability for handheld Valheim torches only.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Infinite Torch by BenjSammy")] [assembly: AssemblyTitle("InfiniteTorch")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BenjSammy.InfiniteTorch { [BepInPlugin("benjsammy.infinitetorch", "Infinite Torch by BenjSammy", "1.0.0")] public sealed class InfiniteTorchPlugin : BaseUnityPlugin { public const string PluginGuid = "benjsammy.infinitetorch"; public const string PluginName = "Infinite Torch by BenjSammy"; public const string PluginVersion = "1.0.0"; private Harmony _harmony; private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown _harmony = new Harmony("benjsammy.infinitetorch"); try { Type type = AccessTools.TypeByName("ItemDrop"); Type itemData = type?.GetNestedType("ItemData", BindingFlags.Public | BindingFlags.NonPublic); Type humanoid = AccessTools.TypeByName("Humanoid"); Type inventory = AccessTools.TypeByName("Inventory"); int num = TorchPatches.Install(_harmony, itemData, humanoid, inventory, type, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Infinite Torch 1.0.0 by BenjSammy active (" + num + " hooks). Handheld torches only. Install on every player's client; server-only installation is insufficient.")); } catch (Exception ex) { _harmony.UnpatchSelf(); TorchPatches.Reset(); ((BaseUnityPlugin)this).Logger.LogError((object)("Infinite Torch could not start: incompatible game API or missing dependency. " + ex)); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } TorchPatches.Reset(); } } internal sealed class TorchController { private const BindingFlags Fields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private readonly Type _itemDataType; private readonly FieldInfo _shared; private readonly FieldInfo _itemType; private readonly FieldInfo _durability; private readonly FieldInfo _usesDurability; private readonly FieldInfo _timeDrain; private readonly FieldInfo _attackDrain; private readonly MethodInfo _getMaxDurability; private readonly object _torchType; internal TorchController(Type itemDataType) { _itemDataType = itemDataType ?? throw new TypeLoadException("ItemDrop.ItemData was not found."); _shared = RequiredField(itemDataType, "m_shared"); Type fieldType = _shared.FieldType; _itemType = RequiredField(fieldType, "m_itemType"); if (!_itemType.FieldType.IsEnum || !Enum.IsDefined(_itemType.FieldType, "Torch")) { throw new MissingMemberException("ItemDrop.ItemData.ItemType.Torch was not found."); } _torchType = Enum.Parse(_itemType.FieldType, "Torch"); _durability = RequiredField(itemDataType, "m_durability", typeof(float)); _usesDurability = RequiredField(fieldType, "m_useDurability", typeof(bool)); _timeDrain = RequiredField(fieldType, "m_durabilityDrain", typeof(float)); _attackDrain = RequiredField(fieldType, "m_useDurabilityDrain", typeof(float)); _getMaxDurability = itemDataType.GetMethod("GetMaxDurability", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (_getMaxDurability == null || _getMaxDurability.ReturnType != typeof(float)) { throw new MissingMethodException(itemDataType.FullName, "GetMaxDurability()"); } } internal bool Protect(object item) { if (item == null || !_itemDataType.IsInstanceOfType(item)) { return false; } object value = _shared.GetValue(item); if (value == null || !_torchType.Equals(_itemType.GetValue(value))) { return false; } float num = (float)_getMaxDurability.Invoke(item, null); if (float.IsNaN(num) || float.IsInfinity(num) || num <= 0f) { return false; } _durability.SetValue(item, num); _usesDurability.SetValue(value, false); _timeDrain.SetValue(value, 0f); _attackDrain.SetValue(value, 0f); return true; } private static FieldInfo RequiredField(Type type, string name, Type expectedType = null) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || (expectedType != null && field.FieldType != expectedType)) { throw new MissingFieldException(type.FullName, name); } return field; } } internal static class TorchPatches { private static TorchController _controller; private static FieldInfo _dropItem; private static MethodInfo _getAllItems; private static Action<string> _warning; private static bool _reportedError; internal static int Install(Harmony harmony, Type itemData, Type humanoid, Type inventory, Type itemDrop, Action<string> warning) { _controller = new TorchController(itemData); _warning = warning; _reportedError = false; if (humanoid == null) { throw new TypeLoadException("Humanoid was not found."); } MethodInfo[] array = WithItemFirstArgument(humanoid, "EquipItem", itemData); MethodInfo[] array2 = WithItemFirstArgument(humanoid, "DrainEquipedItemDurability", itemData); if (array.Length == 0) { throw new MissingMethodException("Humanoid.EquipItem(ItemData, ...)"); } if (array2.Length == 0) { throw new MissingMethodException("Humanoid.DrainEquipedItemDurability(ItemData, ...)"); } int num = 0; MethodInfo[] array3 = array; foreach (MethodInfo methodInfo in array3) { harmony.Patch((MethodBase)methodInfo, Hook("BeforeEquip"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } array3 = array2; foreach (MethodInfo methodInfo2 in array3) { harmony.Patch((MethodBase)methodInfo2, Hook("BeforeDrain"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } _dropItem = ((itemDrop == null) ? null : AccessTools.Field(itemDrop, "m_itemData")); MethodInfo methodInfo3 = ((itemDrop == null) ? null : AccessTools.DeclaredMethod(itemDrop, "Awake", Type.EmptyTypes, (Type[])null)); if (_dropItem != null && _dropItem.FieldType == itemData && methodInfo3 != null) { harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, Hook("AfterItemAwake"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } else { warning?.Invoke("ItemDrop.Awake hook unavailable; handheld torches are still protected when equipped."); } _getAllItems = ((inventory == null) ? null : AccessTools.Method(inventory, "GetAllItems", Type.EmptyTypes, (Type[])null)); MethodInfo[] array4 = ((inventory == null) ? new MethodInfo[0] : (from method in AccessTools.GetDeclaredMethods(inventory) where method.Name == "Load" && !method.IsStatic select method).ToArray()); if (_getAllItems != null && typeof(IEnumerable).IsAssignableFrom(_getAllItems.ReturnType) && array4.Length != 0) { array3 = array4; foreach (MethodInfo methodInfo4 in array3) { harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, Hook("AfterInventoryLoad"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } } else { warning?.Invoke("Inventory.Load hook unavailable; existing handheld torches are restored when equipped."); } return num; } private static MethodInfo[] WithItemFirstArgument(Type type, string name, Type itemData) { return (from method in AccessTools.GetDeclaredMethods(type) where method.Name == name && !method.IsStatic && method.GetParameters().Length != 0 && method.GetParameters()[0].ParameterType == itemData select method).ToArray(); } private static HarmonyMethod Hook(string name) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return new HarmonyMethod(typeof(TorchPatches).GetMethod(name, BindingFlags.Static | BindingFlags.NonPublic)); } private static bool ProtectSafely(object item) { try { return _controller != null && _controller.Protect(item); } catch (Exception exception) { Report(exception); return false; } } private static void BeforeEquip(object __0) { ProtectSafely(__0); } private static bool BeforeDrain(object __0) { return !ProtectSafely(__0); } private static void AfterItemAwake(object __instance) { try { if (__instance != null && _dropItem != null) { ProtectSafely(_dropItem.GetValue(__instance)); } } catch (Exception exception) { Report(exception); } } private static void AfterInventoryLoad(object __instance) { try { if (__instance == null || _getAllItems == null || !(_getAllItems.Invoke(__instance, null) is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { ProtectSafely(item); } } catch (Exception exception) { Report(exception); } } private static void Report(Exception exception) { if (!_reportedError) { _reportedError = true; _warning?.Invoke("Infinite Torch encountered an incompatible item; default game behaviour is retained. " + exception); } } internal static void Reset() { _controller = null; _dropItem = null; _getAllItems = null; _warning = null; _reportedError = false; } } }