Decompiled source of AmmoBag v1.0.0

BepInEx/plugins/AmmoBag.dll

Decompiled 8 hours ago
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using AmmoBag.Patches;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AmmoBag")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AmmoBag")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("da0de89f-9696-4ca2-a169-d360d37a3b8f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AmmoBag
{
	internal static class AmmoBagHelper
	{
		internal const int encode_base_number = 10000;

		internal static int FindAmmoInBelt(PlayerControllerB player, ShotgunItem __instance)
		{
			int num = -1;
			for (int i = 0; i < player.ItemSlots.Length; i++)
			{
				num = CheckSlot(__instance, player.ItemSlots[i], i, isUtilitySlot: false);
				if (num != -1)
				{
					BeltBagPatchBase.logSource.LogInfo((object)("Found shell at " + num));
					return num;
				}
			}
			num = CheckSlot(__instance, player.ItemOnlySlot, -1, isUtilitySlot: true);
			if (num != -1)
			{
				BeltBagPatchBase.logSource.LogInfo((object)("Found shell in utilitySlot at " + num));
			}
			else
			{
				BeltBagPatchBase.logSource.LogInfo((object)"No shells found");
			}
			return num;
		}

		private static int CheckSlot(ShotgunItem __instance, GrabbableObject slot, int bagSlotIndex, bool isUtilitySlot)
		{
			if ((Object)(object)slot == (Object)null)
			{
				return -1;
			}
			BeltBagItem val = (BeltBagItem)(object)((slot is BeltBagItem) ? slot : null);
			if ((Object)(object)val == (Object)null)
			{
				return -1;
			}
			int num = FindAmmoInBag(val, __instance.gunCompatibleAmmoID);
			if (num != -1)
			{
				return EncodeIndex(bagSlotIndex, isUtilitySlot, num);
			}
			return -1;
		}

		private static int FindAmmoInBag(BeltBagItem bag, int ammoTypeID)
		{
			for (int i = 0; i < bag.objectsInBag.Count; i++)
			{
				GrabbableObject val = bag.objectsInBag[i];
				if (!((Object)(object)val == (Object)null))
				{
					GunAmmo val2 = (GunAmmo)(object)((val is GunAmmo) ? val : null);
					if ((Object)(object)val2 != (Object)null && val2.ammoType == ammoTypeID)
					{
						return i;
					}
				}
			}
			return -1;
		}

		private static int EncodeIndex(int beltBagIndex, bool isBagInUtilitySlot, int ammoInBagIndex)
		{
			int num = (isBagInUtilitySlot ? 1000 : ((beltBagIndex + 1) * 100));
			return 10000 + num + ammoInBagIndex;
		}

		internal static (int beltBagSlotIndex, bool isBagInUtilitySlot, int ammoInBagIndex) DecodeIndex(int encodedIndex)
		{
			int num = encodedIndex - 10000;
			if (num >= 1000)
			{
				int item = num - 1000;
				return (-1, true, item);
			}
			int item2 = num / 100 - 1;
			int item3 = num % 100;
			return (item2, false, item3);
		}
	}
	[BepInPlugin("PixelIndieDev_AmmoBag", "Ammo Bag", "1.0.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class BeltBagPatchBase : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("PixelIndieDev_AmmoBag");

		private static BeltBagPatchBase instance;

		internal static GameObject networkAmmo;

		internal static ManualLogSource logSource;

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if ((Object)(object)instance == (Object)null)
			{
				instance = this;
			}
			logSource = Logger.CreateLogSource("PixelIndieDev_AmmoBag");
			networkAmmo = new GameObject("AmmoNetworking");
			networkAmmo.AddComponent<NetworkObject>();
			networkAmmo.AddComponent<AmmoNetworking>();
			((Object)networkAmmo).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)networkAmmo);
			NetworkPrefabs.RegisterNetworkPrefab(networkAmmo);
			harmony.PatchAll(typeof(BeltBagPatchBase));
			harmony.PatchAll(typeof(ShotgunPatch));
			harmony.PatchAll(typeof(PlayerPatch));
			harmony.PatchAll(typeof(NetworkPatch));
			harmony.PatchAll(typeof(GameNetworkManagerPatch));
			logSource.LogInfo((object)"Ammo Bag (version - 1.0.0.0): patches applied successfully");
		}
	}
	internal static class ModInfo
	{
		internal const string modGUID = "PixelIndieDev_AmmoBag";

		internal const string modName = "Ammo Bag";

		internal const string modVersion = "1.0.0.0";
	}
}
namespace AmmoBag.Patches
{
	internal class AmmoNetworking : NetworkBehaviour
	{
		public static AmmoNetworking Instance { get; private set; }

		public override void OnNetworkSpawn()
		{
			Instance = this;
		}

		[ServerRpc(RequireOwnership = false)]
		public void DestroyShellServerRpc(NetworkObjectReference netObjRef)
		{
			NetworkObject val = default(NetworkObject);
			if (((NetworkObjectReference)(ref netObjRef)).TryGet(ref val, (NetworkManager)null))
			{
				BeltBagPatchBase.logSource.LogInfo((object)"Despawn shell");
				val.Despawn(true);
			}
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void OnStartPatch()
		{
			if (NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsHost)
			{
				Object.Instantiate<GameObject>(BeltBagPatchBase.networkAmmo).GetComponent<NetworkObject>().Spawn(false);
			}
		}
	}
	[HarmonyPatch(typeof(NetworkManager))]
	internal static class NetworkPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("SetSingleton")]
		private static void RegisterPrefab()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_000d: 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)
			GameObject val = new GameObject("PixelIndieDev_AmmoBag Prefab");
			((Object)val).hideFlags = (HideFlags)(((Object)val).hideFlags | 0x3D);
			Object.DontDestroyOnLoad((Object)(object)val);
			NetworkObject obj = val.AddComponent<NetworkObject>();
			typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(obj, GetHash("PixelIndieDev_AmmoBag"));
			NetworkManager.Singleton.PrefabHandler.AddNetworkPrefab(val);
		}

		private static uint GetHash(string value)
		{
			return value?.Aggregate(17u, (uint current, char c) => (current * 31) ^ c) ?? 0;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerPatch
	{
		[HarmonyPatch("DestroyItemInSlotAndSync")]
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static bool PatchFindAmmo(PlayerControllerB __instance, int itemSlot)
		{
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			if (itemSlot < 10000)
			{
				return true;
			}
			var (num, flag, num2) = AmmoBagHelper.DecodeIndex(itemSlot);
			BeltBagItem val;
			if (flag)
			{
				GrabbableObject itemOnlySlot = __instance.ItemOnlySlot;
				val = (BeltBagItem)(object)((itemOnlySlot is BeltBagItem) ? itemOnlySlot : null);
			}
			else
			{
				if (num < 0 || num >= __instance.ItemSlots.Length)
				{
					return true;
				}
				GrabbableObject obj = __instance.ItemSlots[num];
				val = (BeltBagItem)(object)((obj is BeltBagItem) ? obj : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (num2 < 0 || num2 >= val.objectsInBag.Count)
			{
				return true;
			}
			GrabbableObject val2 = val.objectsInBag[num2];
			if ((Object)(object)val2 == (Object)null)
			{
				return true;
			}
			val.objectsInBag.RemoveAt(num2);
			NetworkObject component = ((Component)val2).GetComponent<NetworkObject>();
			if ((Object)(object)component != (Object)null && component.IsSpawned)
			{
				if (NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsHost)
				{
					BeltBagPatchBase.logSource.LogInfo((object)("Player " + __instance.playerClientId + " who called shell delete is SERVER"));
					component.Despawn(true);
				}
				else
				{
					BeltBagPatchBase.logSource.LogInfo((object)("Player " + __instance.playerClientId + " who called shell delete is CLIENT"));
					AmmoNetworking.Instance.DestroyShellServerRpc(NetworkObjectReference.op_Implicit(component));
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ShotgunItem))]
	internal class ShotgunPatch
	{
		[HarmonyPatch("FindAmmoInInventory")]
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void PatchFindAmmo(ref int __result, ShotgunItem __instance)
		{
			if (__result == -1)
			{
				PlayerControllerB playerHeldBy = ((GrabbableObject)__instance).playerHeldBy;
				if (!((Object)(object)playerHeldBy == (Object)null))
				{
					__result = AmmoBagHelper.FindAmmoInBelt(playerHeldBy, __instance);
				}
			}
		}
	}
}