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 AmmoTin PVM Compat v1.0.0
AmmoTinPVMCompat.dll
Decompiled 3 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("AmmoTinPVMCompat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("AmmoTinPVMCompat")] [assembly: AssemblyTitle("AmmoTinPVMCompat")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] 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; } } } namespace AmmoTinPVMCompat { internal static class AmmoTinHelper { private const string AmmoTinItemName = "Ammo Tin"; private static FieldInfo? _maxReloadsField; private static FieldInfo? _drainCostField; private static bool _reflectionInit; private static readonly BindingFlags BF = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static void InitReflection() { if (_reflectionInit) { return; } _reflectionInit = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("LethalCompanyAmmoTin.ModAmmoTinMain"); if (!(type == null)) { _maxReloadsField = type.GetField("maxShotgunReloads", BF); _drainCostField = type.GetField("shotgunDrainCost", BF); break; } } } private static float GetDrainCost() { InitReflection(); if (_drainCostField != null) { object value = _drainCostField.GetValue(null); if (value is float) { return (float)value; } object obj = (value?.GetType().GetProperty("Value"))?.GetValue(value); if (obj is float) { return (float)obj; } } int maxReloads = GetMaxReloads(); if (maxReloads <= 0) { return 0.125f; } return 1f / (float)maxReloads; } private static int GetMaxReloads() { InitReflection(); if (_maxReloadsField != null) { object value = _maxReloadsField.GetValue(null); if (value is int) { return (int)value; } object obj = (value?.GetType().GetProperty("Value"))?.GetValue(value); if (obj is int) { return (int)obj; } } return 8; } internal static int FindAmmoTinSlot(object? player) { if (player == null) { return -1; } if (!(player.GetType().GetField("ItemSlots", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(player) is object[] array)) { return -1; } for (int i = 0; i < array.Length; i++) { object obj = array[i]; if (obj == null) { continue; } object obj2 = obj.GetType().GetField("itemProperties", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj); if (obj2 != null && !(obj2.GetType().GetField("itemName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj2) as string != "Ammo Tin")) { object obj3 = obj.GetType().GetField("insertedBattery", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj); if (obj3 != null && obj3.GetType().GetField("charge", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj3) is float num && num >= GetDrainCost()) { return i; } } } return -1; } internal static void DrainAmmoTin(object player, int slot) { if (!(player.GetType().GetField("ItemSlots", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(player) is object[] array) || slot < 0 || slot >= array.Length) { return; } object obj = array[slot]; if (obj == null) { return; } object obj2 = obj.GetType().GetField("insertedBattery", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj); if (obj2 != null) { FieldInfo field = obj2.GetType().GetField("charge", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null)) { float drainCost = GetDrainCost(); float num = Mathf.Clamp01((float)(field.GetValue(obj2) ?? ((object)0f)) - drainCost); field.SetValue(obj2, num); Plugin.Log.LogDebug((object)$"AmmoTinPVMCompat: Drained tin (slot {slot}) — charge now {num:P0}"); } } } } internal static class MyPluginInfo { public const string PLUGIN_GUID = "olyvion.ammotinpvmcompat"; public const string PLUGIN_NAME = "AmmoTin PVM Compat"; public const string PLUGIN_VERSION = "1.0.0"; } internal static class TinReloadState { private static readonly Dictionary<object, int> _active = new Dictionary<object, int>(); internal static Dictionary<object, int> All => _active; internal static void Set(object gun, int slot) { _active[gun] = slot; } internal static void Clear(object gun) { _active.Remove(gun); } } internal static class WeaponPatches { private static readonly BindingFlags BF = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static FieldInfo? GetField(Type t, string n) { FieldInfo? field = t.GetField(n, BF); if ((object)field == null) { Type? baseType = t.BaseType; if ((object)baseType == null) { return null; } field = baseType.GetField(n, BF); } return field; } public static void ReloadedGun_Postfix(object __instance, ref bool __result) { if (!__result) { Type type = __instance.GetType(); object player = GetField(type, "playerHeldBy")?.GetValue(__instance); int num = AmmoTinHelper.FindAmmoTinSlot(player); if (num != -1) { AmmoTinHelper.DrainAmmoTin(player, num); GetField(type, "ammoSlotToUse")?.SetValue(__instance, num); TinReloadState.Set(__instance, num); __result = true; Plugin.Log.LogInfo((object)$"[PVMCompat] {type.Name}: reloaded via Ammo Tin slot {num}"); } } } } internal static class DestroyItemSlotPatch { private static readonly BindingFlags BF = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; public static bool Prefix(object __instance, int itemSlot) { foreach (KeyValuePair<object, int> item in new Dictionary<object, int>(TinReloadState.All)) { if (item.Value == itemSlot && (item.Key.GetType().GetField("playerHeldBy", BF) ?? item.Key.GetType().BaseType?.GetField("playerHeldBy", BF))?.GetValue(item.Key) == __instance) { TinReloadState.Clear(item.Key); Plugin.Log.LogDebug((object)$"[PVMCompat] Blocked DestroyItemInSlotAndSync({itemSlot})"); return false; } } return true; } } [BepInPlugin("olyvion.ammotinpvmcompat", "AmmoTin PVM Compat", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private readonly Harmony _harmony = new Harmony("olyvion.ammotinpvmcompat"); public static ManualLogSource Log { get; private set; } private void Awake() { Log = ((BaseUnityPlugin)this).Logger; try { PatchMethod("PiggyVarietyMod.Patches.M4Item", "ReloadedGun", "ReloadedGun_Postfix"); } catch (Exception arg) { Log.LogError((object)$"Failed to patch M4Item.ReloadedGun: {arg}"); } try { PatchMethod("PiggyVarietyMod.Patches.RevolverItem", "ReloadedGun", "ReloadedGun_Postfix"); } catch (Exception arg2) { Log.LogError((object)$"Failed to patch RevolverItem.ReloadedGun: {arg2}"); } try { PatchDestroyItemInSlot(); } catch (Exception arg3) { Log.LogError((object)$"Failed to patch DestroyItemInSlotAndSync: {arg3}"); } Log.LogInfo((object)"AmmoTin PVM Compat v1.0.0 loaded!"); } private void PatchMethod(string typeName, string methodName, string patchMethodName) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { type = assemblies[i].GetType(typeName); if (type != null) { break; } } if (type == null) { Log.LogError((object)("Could not find type: " + typeName)); return; } MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { Log.LogError((object)("Could not find method: " + typeName + "." + methodName)); return; } MethodInfo method2 = typeof(WeaponPatches).GetMethod(patchMethodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method2 == null) { Log.LogError((object)("Could not find patch method: " + patchMethodName)); return; } _harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)("Patched " + typeName + "." + methodName)); } private void PatchDestroyItemInSlot() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { type = assemblies[i].GetType("GameNetcodeStuff.PlayerControllerB"); if (type != null) { break; } } if (type == null) { Log.LogError((object)"Could not find PlayerControllerB"); return; } MethodInfo method = type.GetMethod("DestroyItemInSlotAndSync", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { Log.LogError((object)"Could not find DestroyItemInSlotAndSync"); return; } MethodInfo method2 = typeof(DestroyItemSlotPatch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _harmony.Patch((MethodBase)method, new HarmonyMethod(method2) { priority = 600 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched PlayerControllerB.DestroyItemInSlotAndSync"); } private static void ReloadedGun_Postfix() { } } }