Please disclose if your mod was created primarily 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 Ballista Reloader v0.217.25
ReloadTurrets.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ReloadTurrets")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Reload Ballista From Nearby Containers")] [assembly: AssemblyCopyright("Copyright Byte-Artificer 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("3f8cf903-7f89-437c-abb5-4a79ecc7573a")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace FriendlyTurrets; public class NearbyContainers : BaseUnityPlugin { public class ConnectionParams { public GameObject connection = null; public Vector3 stationPos; } public static ConfigEntry<float> m_range; public static ConfigEntry<bool> ignoreShipContainers; public static ConfigEntry<bool> ignoreWagonContainers; public static ConfigEntry<bool> ignoreWoodChests; public static ConfigEntry<bool> ignorePrivateChests; public static ConfigEntry<bool> ignoreBlackMetalChests; public static ConfigEntry<bool> ignoreReinforcedChests; public static ConfigEntry<bool> allowChangingAmmoTypes; public static ConfigEntry<int> reloadTurretsBelow; public static ConfigEntry<bool> modEnabled; public static ConfigEntry<bool> isDebug; public static ConfigEntry<bool> printDebugMessages; public static List<Container> containerList = new List<Container>(); public static void Dbgl(string str = "", bool pref = true) { if (isDebug.Value) { Debug.Log((object)((pref ? (typeof(NearbyContainers).Namespace + " ") : "") + str)); } } public static void Init(ConfigFile config) { modEnabled = config.Bind<bool>("General", "Enabled", true, "Enable this mod"); isDebug = config.Bind<bool>("General", "IsDebug", false, "Show debug messages in log"); m_range = config.Bind<float>("General", "ContainerRange", 10f, "The maximum range from which to pull items from"); ignoreShipContainers = config.Bind<bool>("Container Types", "IgnoreShipContainers", false, "If true, will ignore this type of container."); ignoreWagonContainers = config.Bind<bool>("Container Types", "IgnoreWagonContainers", false, "If true, will ignore this type of container."); ignoreWoodChests = config.Bind<bool>("Container Types", "IgnoreWoodChests", false, "If true, will ignore this type of container."); ignorePrivateChests = config.Bind<bool>("Container Types", "IgnorePrivateChests", false, "If true, will ignore this type of container."); ignoreBlackMetalChests = config.Bind<bool>("Container Types", "IgnoreBlackMetalChests", false, "If true, will ignore this type of container."); ignoreReinforcedChests = config.Bind<bool>("Container Types", "IgnoreReinforcedChests", false, "If true, will ignore this type of container."); allowChangingAmmoTypes = config.Bind<bool>("General", "AllowChangingAmmoTypes", true, "If false, ballista will only reload with the previous ammo type when empty."); reloadTurretsBelow = config.Bind<int>("General", "ReloadTurretsBelow", 5, "Ballista will automatically reload when their stored ammo drops below this amount."); if (modEnabled.Value) { } } public static List<Container> GetNearbyContainers(Vector3 center) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) List<Container> list = new List<Container>(); foreach (Container container in containerList) { if ((Object)(object)container != (Object)null && (Object)(object)((Component)container).GetComponentInParent<Piece>() != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)((container != null) ? ((Component)container).transform : null) != (Object)null && container.GetInventory() != null && (m_range.Value <= 0f || Vector3.Distance(center, ((Component)container).transform.position) < m_range.Value) && (!container.m_checkGuardStone || PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false)) && Traverse.Create((object)container).Method("CheckAccess", new object[1] { Player.m_localPlayer.GetPlayerID() }).GetValue<bool>() && !container.IsInUse() && AllowContainerType(container)) { list.Add(container); } } return list; } private static bool AllowContainerType(Container __instance) { Transform parent = ((Component)__instance).gameObject.transform.parent; Ship val = ((parent != null) ? ((Component)parent).GetComponent<Ship>() : null); return (!((Object)(object)val != (Object)null) || !ignoreShipContainers.Value) && (!Object.op_Implicit((Object)(object)__instance.m_wagon) || !ignoreWagonContainers.Value) && (!((Object)__instance).name.StartsWith("piece_chest_wood(") || !ignoreWoodChests.Value) && (!((Object)__instance).name.StartsWith("piece_chest_private(") || !ignorePrivateChests.Value) && (!((Object)__instance).name.StartsWith("piece_chest_blackmetal(") || !ignoreBlackMetalChests.Value) && (!((Object)__instance).name.StartsWith("piece_chest(") || !ignoreReinforcedChests.Value); } public static IEnumerator AddContainer(Container container, ZNetView nview) { yield return null; try { int num; if (container.GetInventory() != null) { if (((nview != null) ? nview.GetZDO() : null) != null) { num = ((((Object)container).name.StartsWith("piece_") || ((Object)container).name.StartsWith("Container") || nview.GetZDO().GetLong(StringExtensionMethods.GetStableHashCode("creator"), 0L) != 0) ? 1 : 0); goto IL_00ad; } } num = 0; goto IL_00ad; IL_00ad: if (num != 0) { containerList.Add(container); } } catch { } } public static void PullResources(Turret turret, int qty, Action<string> loadTurretAction) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) string lastAmmo = turret.GetAmmoItem().m_shared.m_name; Dbgl($"looking for {qty} {lastAmmo} for {((Object)turret).name}"); Dbgl("Allowed ammo types: "); foreach (AmmoType item in turret.m_allowedAmmo) { Dbgl(((Object)item.m_ammo).name + " : " + item.m_ammo.m_itemData.m_shared.m_name); } AmmoType val = turret.m_allowedAmmo.First((AmmoType x) => x.m_ammo.m_itemData.m_shared.m_name == lastAmmo); bool flag = PullResourcesCore(turret, qty, val, loadTurretAction); Dbgl("resournces found: " + flag); if (!flag) { Dbgl($"turret has ammo: {turret.HasAmmo()}"); } if (!allowChangingAmmoTypes.Value || flag || turret.HasAmmo()) { return; } foreach (AmmoType item2 in turret.m_allowedAmmo) { Dbgl("next ammo type: " + ((Object)item2.m_ammo).name); if ((Object)(object)item2.m_ammo == (Object)(object)val.m_ammo) { Dbgl(((Object)item2.m_ammo).name + " is the same as " + ((Object)val.m_ammo).name + ", skipping "); } else if (PullResourcesCore(turret, qty, item2, loadTurretAction)) { break; } } } private static bool PullResourcesCore(Turret turret, int qty, AmmoType ammoType, Action<string> loadTurretAction) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) string name = ammoType.m_ammo.m_itemData.m_shared.m_name; Dbgl($"looking for {qty} {name} for {((Object)turret).name}"); List<Container> nearbyContainers = GetNearbyContainers(((Component)turret).transform.position); string text = name; int num = 0; bool result = false; foreach (Container item2 in nearbyContainers) { lock (item2) { Dbgl($"checking container {item2}"); Inventory inventory = item2.GetInventory(); int num2 = Mathf.Min(inventory.CountItems(text, -1, true), qty - num); Dbgl($"Container at {((Component)item2).transform.position} has {inventory.CountItems(text, -1, true)}"); if (num2 == 0) { continue; } for (int i = 0; i < inventory.GetAllItems().Count; i++) { ItemData item = inventory.GetItem(i); if (!(item.m_shared.m_name == text)) { continue; } Dbgl($"Got stack of {item.m_stack} {text}"); int num3 = Mathf.Min(item.m_stack, qty - num); Dbgl($"Sending {num3} {text} to turret"); int ammo = turret.GetAmmo(); for (int j = 0; j < num3; j++) { loadTurretAction(((Object)ammoType.m_ammo).name); } if (turret.GetAmmo() > ammo) { if (num3 == item.m_stack) { inventory.RemoveItem(i); } else { item.m_stack -= num3; } } result = true; num += num3; Dbgl($"total amount is now {num}/{qty} {text}"); if (num >= qty) { break; } } ((object)item2).GetType().GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(item2, new object[0]); ((object)inventory).GetType().GetMethod("Changed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(inventory, new object[0]); if (num < qty) { continue; } Dbgl("pulled enough " + text); break; } } return result; } } [BepInPlugin("ByteArtificer.ReloadTurretsFromContainers", "Reload Ballista From Nearby Containers", "1.0.1")] [BepInProcess("valheim.exe")] public class ReloadTurrets : BaseUnityPlugin { [HarmonyPatch(typeof(Turret), "ShootProjectile")] public static class Turret_ShootProjectile_Prefix { private static void Postfix(ref Turret __instance) { Turret turret = __instance; int ammo = __instance.GetAmmo(); _logger.LogMessage((object)$"Turret fired, {ammo}/{__instance.m_maxAmmo} ammo remains"); if (ammo < NearbyContainers.reloadTurretsBelow.Value) { _logger.LogMessage((object)"Turret needs reloading"); NearbyContainers.PullResources(__instance, __instance.m_maxAmmo - ammo, delegate(string ammoType) { ((object)turret).GetType().GetMethod("RPC_AddAmmo", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(turret, new object[2] { 0, ammoType }); }); } } } [HarmonyPatch(typeof(Container), "Awake")] private static class Container_Awake_Patch { private static void Postfix(Container __instance, ZNetView ___m_nview) { ((MonoBehaviour)_context).StartCoroutine(NearbyContainers.AddContainer(__instance, ___m_nview)); } } [HarmonyPatch(typeof(Container), "OnDestroyed")] private static class Container_OnDestroyed_Patch { private static void Prefix(Container __instance) { NearbyContainers.containerList.Remove(__instance); } } private readonly Harmony harmony = new Harmony("ByteArtificer.ReloadTurretsFromContainers"); public static ManualLogSource _logger; public static ConfigEntry<bool> ignoreShipContainers; private static ReloadTurrets _context; public void Awake() { _logger = ((BaseUnityPlugin)this).Logger; _context = this; NearbyContainers.Init(((BaseUnityPlugin)this).Config); harmony.PatchAll(); } }