Decompiled source of MultiTargetBallista v1.0.5

marchiori.multitargetballista.dll

Decompiled 18 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Marchiori.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("marchiori.multitargetballista")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("marchiori.multitargetballista")]
[assembly: AssemblyTitle("marchiori.multitargetballista")]
[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 Marchiori.MultiTargetBallista
{
	[BepInPlugin("marchiori.multitargetballista", "Multi Target Ballista", "1.0.3")]
	public sealed class BepinexPlugin : BaseUnityPlugin
	{
		public const string Guid = "marchiori.multitargetballista";

		private void Awake()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.Load(((BaseUnityPlugin)this).Config))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Multi Target Ballista is disabled.");
				return;
			}
			new Harmony("marchiori.multitargetballista").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Multi Target Ballista loaded.");
		}
	}
	internal static class ModConfig
	{
		internal static string EnabledChests { get; private set; } = "";

		internal static bool AmmoFromFirstSlotOnly { get; private set; }

		internal static string InventoryContents { get; private set; } = "";

		internal static bool Load(ConfigFile config)
		{
			bool value = config.Bind<bool>("General", "Enable", true, "Enables or disables this mod (requires game/server restart)").Value;
			EnabledChests = config.Bind<string>("General", "Enabled_chests", "piece_chest_private, piece_chest_grausten", "Types of containers that may be used. Accepted values (in csv format): \"piece_chest_private\", \"piece_chest_wood\", \"piece_chest_iron\", \"piece_chest_blackmetal\", \"piece_chest_grausten\", \"piece_chest_barrel\"").Value;
			AmmoFromFirstSlotOnly = config.Bind<bool>("General", "Ammo_from_first_slot_only", false, "Makes the ballista pull ammo only from the first slot of the container. false to pull from any slots.").Value;
			InventoryContents = config.Bind<string>("General", "Inventory_contents", "ammo, trophies, boss_trophies", "What may be placed inside the containers. Accepted values (in csv format): \"ammo, trophies, boss_trophies\"").Value;
			return value;
		}
	}
	internal static class ModText
	{
		internal const string AlreadyHasInventory = "$mb_1";

		internal const string InventoryFull = "$mb_2";

		internal const string WardOwner = "$mb_3";

		internal const string HoverInventory = "$mb_4";

		internal const string RejectedItem = "$mb_5";

		internal const string CannotOpen = "$msg_cantopen";

		internal const string AddedPrefix = "$msg_added ";
	}
	internal static class ZdoKeys
	{
		internal const string Link = "mb_link";

		internal const string Chest = "mb_chest";

		internal const string Turret = "mb_turret";

		internal const string Hidden = "mb_hidden";

		internal const string Break = "mb_break";

		internal const string BreakPosition = "mb_breakPos";

		internal const string HasTrophies = "mb_hasTrophies";
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class Container_Awake_Patch
	{
		private static void Postfix(Container __instance)
		{
			if (HiddenChestLink.IsHidden(((Component)__instance).GetComponent<ZNetView>()))
			{
				HiddenChestLink.TrackLoadedChest(__instance);
				HiddenChestAppearance.Apply(((Component)__instance).gameObject);
				HiddenChestLink.Register(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Container), "OnDestroyed")]
	internal static class Container_OnDestroyed_Patch
	{
		private static void Postfix(Container __instance)
		{
			LinkedChestBreak.Detach(__instance);
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	internal static class Inventory_AddItem_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			return InventoryAdmission.Apply(InventoryAdmission.Evaluate(__instance, item), ref __result);
		}
	}
	[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int)
	})]
	internal static class Inventory_CanAddItem_Item_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			return InventoryAdmission.Apply(InventoryAdmission.Evaluate(__instance, item), ref __result);
		}
	}
	[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
	{
		typeof(GameObject),
		typeof(int)
	})]
	internal static class Inventory_CanAddItem_Prefab_Patch
	{
		private static bool Prefix(Inventory __instance, GameObject prefab, ref bool __result)
		{
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return true;
			}
			ItemDrop component = prefab.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			ItemData itemData = component.m_itemData;
			if (itemData != null && (Object)(object)itemData.m_dropPrefab == (Object)null)
			{
				itemData.m_dropPrefab = prefab;
			}
			return InventoryAdmission.Apply(InventoryAdmission.Evaluate(__instance, itemData), ref __result);
		}
	}
	[HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[]
	{
		typeof(Inventory),
		typeof(ItemData),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	internal static class Inventory_MoveItemAmount_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			return InventoryAdmission.Apply(InventoryAdmission.Evaluate(__instance, item), ref __result);
		}
	}
	[HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[]
	{
		typeof(Inventory),
		typeof(ItemData)
	})]
	internal static class Inventory_MoveItem_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item)
		{
			return InventoryAdmission.Evaluate(__instance, item).RunOriginal;
		}
	}
	[HarmonyPatch(typeof(Localization), "SetupLanguage")]
	internal static class Localization_SetupLanguage_Patch
	{
		private static void Postfix(Localization __instance)
		{
			Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(OnLanguageChanged));
			Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(OnLanguageChanged));
			Apply(__instance, __instance.GetSelectedLanguage());
		}

		private static void OnLanguageChanged()
		{
			if (Localization.instance != null)
			{
				Apply(Localization.instance, Localization.instance.GetSelectedLanguage());
			}
		}

		private static void Apply(Localization localization, string language)
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			LanguageFiles.Apply(localization, language, directoryName, "mb");
		}
	}
	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	internal static class Player_TryPlacePiece_Patch
	{
		private static bool Prefix(Player __instance, Piece piece, ref bool __result)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)piece == (Object)null)
			{
				return true;
			}
			HashSet<string> enabledChests = BallistaRules.ParseList(ModConfig.EnabledChests);
			if (!BallistaRules.IsEnabledChest(((Object)((Component)piece).gameObject).name, enabledChests))
			{
				return true;
			}
			if (!PieceAim.TryGetTurret(__instance, out var turret))
			{
				return true;
			}
			if (HiddenChestLink.HasLink(turret))
			{
				((Character)__instance).Message((MessageType)2, Localization.instance.Localize("$mb_1"), 0, (Sprite)null, false);
				__result = false;
				return false;
			}
			if (!BallistaRules.PlayerMayAttach(WardCoverage.OwnerIds(((Component)turret).transform.position), __instance.GetPlayerID()))
			{
				((Character)__instance).Message((MessageType)2, Localization.instance.Localize("$mb_3"), 0, (Sprite)null, false);
				__result = false;
				return false;
			}
			__result = ChestAttacher.TryAttach(__instance, piece, turret);
			return false;
		}
	}
	[HarmonyPatch(typeof(Turret), "Awake")]
	internal static class Turret_Awake_Patch
	{
		private static void Postfix(Turret __instance)
		{
			HiddenChestLink.TrackLoadedTurret(__instance);
		}
	}
	[HarmonyPatch(typeof(Turret), "GetHoverText")]
	internal static class Turret_GetHoverText_Patch
	{
		private static void Postfix(Turret __instance, ref string __result)
		{
			if (HiddenChestLink.HasLink(__instance))
			{
				string text = TurretTargets.HoverLine(__instance);
				if (text != null)
				{
					__result = text;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Turret), "Interact")]
	internal static class Turret_Interact_Patch
	{
		private static bool Prefix(Turret __instance, Humanoid character, bool hold, ref bool __result)
		{
			if (!HiddenChestLink.HasLink(__instance))
			{
				return true;
			}
			if (hold)
			{
				__result = false;
				return false;
			}
			Container val = HiddenChestLink.FindChest(__instance);
			if ((Object)(object)val == (Object)null)
			{
				__result = false;
				return false;
			}
			__result = val.Interact(character, false, false);
			return false;
		}
	}
	[HarmonyPatch(typeof(Turret), "OnDestroyed")]
	internal static class Turret_OnDestroyed_Patch
	{
		private static void Postfix(Turret __instance)
		{
			LinkedChestBreak.BreakWithTurret(__instance);
		}
	}
	[HarmonyPatch(typeof(Turret), "UpdateTarget")]
	internal static class Turret_UpdateTarget_Patch
	{
		private static bool Prefix(Turret __instance)
		{
			return TurretMaintenance.AllowVanillaTargetSearch(__instance);
		}
	}
	[HarmonyPatch(typeof(Turret), "UseItem")]
	internal static class Turret_UseItem_Patch
	{
		private static bool Prefix(Turret __instance, ItemData item, ref bool __result)
		{
			if (!HiddenChestLink.HasLink(__instance) || item == null)
			{
				return true;
			}
			ItemCategory itemCategory = ItemClassifier.Categorize(__instance, item);
			if (itemCategory != ItemCategory.Ammo && itemCategory != ItemCategory.Trophy && itemCategory != ItemCategory.BossTrophy)
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(WearNTear), "Destroy")]
	internal static class WearNTear_Destroy_Patch
	{
		private static void Prefix(WearNTear __instance)
		{
			LinkedChestBreak.MoveToStoredPosition(__instance);
		}
	}
	[HarmonyPatch(typeof(WearNTear), "UpdateSupport")]
	internal static class WearNTear_UpdateSupport_Patch
	{
		private static void Postfix(WearNTear __instance)
		{
			if (HiddenChestLink.IsHidden(((Component)__instance).GetComponent<ZNetView>()))
			{
				HiddenChestAppearance.HoldFullSupport(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetScene_Awake_Patch
	{
		private static void Postfix()
		{
			BossTrophyCatalog.Remember();
		}
	}
	[HarmonyPatch(typeof(ZNetView), "Awake")]
	internal static class ZNetView_Awake_Patch
	{
		private static void Postfix(ZNetView __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && HiddenChestLink.IsHidden(__instance))
			{
				HiddenChestAppearance.Apply(((Component)__instance).gameObject);
				Container component = ((Component)__instance).GetComponent<Container>();
				if ((Object)(object)component != (Object)null)
				{
					HiddenChestLink.TrackLoadedChest(component);
				}
			}
		}
	}
	internal enum ItemCategory
	{
		Ammo,
		Trophy,
		BossTrophy,
		Other
	}
	internal readonly struct SlotItem
	{
		internal string PrefabName { get; }

		internal ItemCategory Category { get; }

		internal int Stack { get; }

		internal static SlotItem Empty => new SlotItem("", ItemCategory.Other, 0);

		internal SlotItem(string prefabName, ItemCategory category, int stack)
		{
			PrefabName = prefabName ?? "";
			Category = category;
			Stack = stack;
		}
	}
	internal readonly struct AmmoTake
	{
		internal int SlotIndex { get; }

		internal string PrefabName { get; }

		internal int Amount { get; }

		internal AmmoTake(int slotIndex, string prefabName, int amount)
		{
			SlotIndex = slotIndex;
			PrefabName = prefabName ?? "";
			Amount = amount;
		}
	}
	internal static class BallistaRules
	{
		internal static string NormalizePieceName(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return "";
			}
			name = name.Trim();
			if (name.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				name = name.Substring(0, name.Length - "(Clone)".Length);
			}
			name = name.Trim().Trim(new char[1] { '"' });
			if (name.Equals("piece_chest_iron", StringComparison.OrdinalIgnoreCase))
			{
				return "piece_chest";
			}
			return name;
		}

		internal static HashSet<string> ParseList(string csv)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			if (string.IsNullOrWhiteSpace(csv))
			{
				return hashSet;
			}
			csv = csv.Trim().Trim(new char[1] { '"' });
			string[] array = csv.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = NormalizePieceName(array[i]);
				if (text.Length > 0)
				{
					hashSet.Add(text);
				}
			}
			return hashSet;
		}

		internal static bool IsEnabledChest(string pieceName, ISet<string> enabledChests)
		{
			return enabledChests?.Contains(NormalizePieceName(pieceName)) ?? false;
		}

		internal static bool CategoryAllowed(ItemCategory category, ISet<string> contents)
		{
			if (contents == null)
			{
				return false;
			}
			return category switch
			{
				ItemCategory.Ammo => contents.Contains("ammo"), 
				ItemCategory.Trophy => contents.Contains("trophies"), 
				ItemCategory.BossTrophy => contents.Contains("boss_trophies"), 
				_ => false, 
			};
		}

		internal static bool PlayerMayAttach(IReadOnlyCollection<long> coveringWardOwnerIds, long playerId)
		{
			if (coveringWardOwnerIds == null || coveringWardOwnerIds.Count == 0)
			{
				return true;
			}
			foreach (long coveringWardOwnerId in coveringWardOwnerIds)
			{
				if (coveringWardOwnerId != playerId)
				{
					return false;
				}
			}
			return true;
		}

		internal static bool TargetsEverything(IReadOnlyList<SlotItem> slots)
		{
			if (slots == null)
			{
				return true;
			}
			for (int i = 0; i < slots.Count; i++)
			{
				SlotItem slotItem = slots[i];
				if (slotItem.Stack > 0 && (slotItem.Category == ItemCategory.Trophy || slotItem.Category == ItemCategory.BossTrophy))
				{
					return false;
				}
			}
			return true;
		}

		internal static List<string> TrophyTargetNames(IReadOnlyList<SlotItem> slots, ISet<string> mappedTrophyNames)
		{
			List<string> list = new List<string>();
			if (slots == null || mappedTrophyNames == null)
			{
				return list;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			for (int i = 0; i < slots.Count; i++)
			{
				SlotItem slotItem = slots[i];
				if (slotItem.Stack > 0 && (slotItem.Category == ItemCategory.Trophy || slotItem.Category == ItemCategory.BossTrophy) && mappedTrophyNames.Contains(slotItem.PrefabName) && hashSet.Add(slotItem.PrefabName))
				{
					list.Add(slotItem.PrefabName);
				}
			}
			return list;
		}

		internal static List<AmmoTake> PlanAmmoPull(IReadOnlyList<SlotItem> slots, int magazineCount, int magazineMax, string loadedPrefab, bool firstSlotOnly)
		{
			List<AmmoTake> list = new List<AmmoTake>();
			if (slots == null || slots.Count == 0 || magazineMax <= 0 || magazineCount < 0 || magazineCount >= magazineMax)
			{
				return list;
			}
			int num = (firstSlotOnly ? 1 : slots.Count);
			if (num > slots.Count)
			{
				num = slots.Count;
			}
			string text = null;
			if (magazineCount > 0)
			{
				if (string.IsNullOrEmpty(loadedPrefab))
				{
					return list;
				}
				text = loadedPrefab;
			}
			else
			{
				for (int i = 0; i < num; i++)
				{
					SlotItem slotItem = slots[i];
					if (slotItem.Stack > 0 && slotItem.Category == ItemCategory.Ammo && slotItem.PrefabName.Length > 0)
					{
						text = slotItem.PrefabName;
						break;
					}
				}
				if (text == null)
				{
					return list;
				}
			}
			int num2 = magazineMax - magazineCount;
			for (int j = 0; j < num; j++)
			{
				if (num2 <= 0)
				{
					break;
				}
				SlotItem slotItem2 = slots[j];
				if (slotItem2.Stack > 0 && slotItem2.Category == ItemCategory.Ammo && string.Equals(slotItem2.PrefabName, text, StringComparison.Ordinal))
				{
					int num3 = ((slotItem2.Stack < num2) ? slotItem2.Stack : num2);
					list.Add(new AmmoTake(j, text, num3));
					num2 -= num3;
				}
			}
			return list;
		}

		internal static int MagazineLoadAmount(int magazineCount, int magazineMax, int stack, bool acceptedType)
		{
			if (!acceptedType || stack <= 0 || magazineMax <= 0 || magazineCount < 0 || magazineCount >= magazineMax)
			{
				return 0;
			}
			int num = magazineMax - magazineCount;
			if (stack >= num)
			{
				return num;
			}
			return stack;
		}
	}
	internal static class BossTrophyCatalog
	{
		private static readonly HashSet<string> Names = new HashSet<string>(StringComparer.Ordinal);

		internal static void Remember()
		{
			if ((Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null)
			{
				return;
			}
			List<GameObject> prefabs = ZNetScene.instance.m_prefabs;
			for (int i = 0; i < prefabs.Count; i++)
			{
				GameObject val = prefabs[i];
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				OfferingBowl component = val.GetComponent<OfferingBowl>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.m_bossItem == (Object)null))
				{
					Names.Add(((Object)component.m_bossItem).name);
					if (component.m_bossItem.m_itemData != null && component.m_bossItem.m_itemData.m_shared != null)
					{
						Names.Add(component.m_bossItem.m_itemData.m_shared.m_name);
					}
				}
			}
		}

		internal static bool Contains(string name)
		{
			if (name != null)
			{
				return Names.Contains(name);
			}
			return false;
		}
	}
	internal static class ChestAttacher
	{
		internal static bool TryAttach(Player player, Piece piece, Turret turret)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0031: 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)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)turret).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return false;
			}
			Vector3 position = ((Component)turret).transform.position;
			Quaternion rotation = ((Component)turret).transform.rotation;
			GameObject val = Object.Instantiate<GameObject>(((Component)piece).gameObject, position, rotation);
			ZNetView component2 = val.GetComponent<ZNetView>();
			Piece component3 = val.GetComponent<Piece>();
			if ((Object)(object)component2 == (Object)null || component2.GetZDO() == null || (Object)(object)component3 == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				return false;
			}
			component3.SetCreator(player.GetPlayerID(), LocalPlatformUser());
			WearNTear component4 = val.GetComponent<WearNTear>();
			if ((Object)(object)component4 != (Object)null)
			{
				component4.OnPlaced();
			}
			ZDO zDO = component2.GetZDO();
			zDO.Set("mb_hidden", true);
			zDO.Set("mb_turret", component.GetZDO().m_uid);
			component.GetZDO().Set("mb_chest", zDO.m_uid);
			HiddenChestLink.Bind(turret, val.GetComponent<Container>());
			if (player.PlacementCostDisabled)
			{
				zDO.Set(ZDOVars.s_cheated, true);
			}
			HiddenChestAppearance.Apply(val);
			TurretTargets.Clear(turret);
			if (piece.m_placeEffect != null)
			{
				piece.m_placeEffect.Create(position, rotation, val.transform, 1f, -1, ((Character)player).GetZDOID());
			}
			return true;
		}

		private static PlatformUserID LocalPlatformUser()
		{
			//IL_0015: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			if (PlatformManager.DistributionPlatform == null || PlatformManager.DistributionPlatform.LocalUser == null)
			{
				return default(PlatformUserID);
			}
			return ((IUser)PlatformManager.DistributionPlatform.LocalUser).PlatformUserID;
		}
	}
	internal static class ChestInventory
	{
		internal static List<SlotItem> ReadSlots(Container container, Turret turret)
		{
			List<SlotItem> list = new List<SlotItem>();
			Inventory val = (((Object)(object)container != (Object)null) ? container.GetInventory() : null);
			if (val == null)
			{
				return list;
			}
			int width = val.GetWidth();
			int height = val.GetHeight();
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					ItemData itemAt = val.GetItemAt(j, i);
					if (itemAt == null)
					{
						list.Add(SlotItem.Empty);
						continue;
					}
					ItemCategory itemCategory = ItemClassifier.Categorize(turret, itemAt);
					string prefabName = ((itemCategory == ItemCategory.Ammo && Object.op_Implicit((Object)(object)itemAt.m_dropPrefab)) ? ((Object)itemAt.m_dropPrefab).name : itemAt.m_shared.m_name);
					list.Add(new SlotItem(prefabName, itemCategory, itemAt.m_stack));
				}
			}
			return list;
		}

		internal static void PullAmmo(Turret turret, Container container, IReadOnlyList<SlotItem> slots)
		{
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			if (turret.m_maxAmmo <= 0 || turret.GetAmmo() != 0)
			{
				return;
			}
			ZNetView component = ((Component)container).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
				return;
			}
			string loadedPrefab = ((turret.GetAmmo() > 0) ? turret.GetAmmoType() : "");
			List<AmmoTake> list = BallistaRules.PlanAmmoPull(slots, turret.GetAmmo(), turret.m_maxAmmo, loadedPrefab, ModConfig.AmmoFromFirstSlotOnly);
			if (list.Count == 0)
			{
				return;
			}
			Inventory inventory = container.GetInventory();
			int width = inventory.GetWidth();
			if (width <= 0)
			{
				return;
			}
			int num = 0;
			string prefabName = list[0].PrefabName;
			for (int i = 0; i < list.Count; i++)
			{
				ItemData itemAt = inventory.GetItemAt(list[i].SlotIndex % width, list[i].SlotIndex / width);
				if (itemAt != null)
				{
					int num2 = ((list[i].Amount < itemAt.m_stack) ? list[i].Amount : itemAt.m_stack);
					if (num2 > 0)
					{
						inventory.RemoveItem(itemAt, num2);
						num += num2;
					}
				}
			}
			if (num > 0)
			{
				ZDO zDO = ((Component)turret).GetComponent<ZNetView>().GetZDO();
				zDO.Set(ZDOVars.s_ammo, zDO.GetInt(ZDOVars.s_ammo, 0) + num, false);
				zDO.Set(ZDOVars.s_ammoType, prefabName);
				if (turret.m_addAmmoEffect != null)
				{
					turret.m_addAmmoEffect.Create(((Component)turret).transform.position, ((Component)turret).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
				}
			}
		}
	}
	internal static class HiddenChestAppearance
	{
		internal static void Apply(GameObject chest)
		{
			//IL_0034: 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)
			if (Object.op_Implicit((Object)(object)chest))
			{
				ZNetView component = chest.GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid())
				{
					component.SetLocalScale(Vector3.zero);
				}
				else
				{
					chest.transform.localScale = Vector3.zero;
				}
				Collider[] componentsInChildren = chest.GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].enabled = false;
				}
				Renderer[] componentsInChildren2 = chest.GetComponentsInChildren<Renderer>(true);
				for (int j = 0; j < componentsInChildren2.Length; j++)
				{
					componentsInChildren2[j].enabled = false;
				}
				WearNTear component2 = chest.GetComponent<WearNTear>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.m_noSupportWear = false;
					component2.m_noRoofWear = false;
					component2.m_ashDamageImmune = true;
					component2.m_snowDamageImmune = true;
					component2.m_burnable = false;
				}
				Container component3 = chest.GetComponent<Container>();
				if ((Object)(object)component3 != (Object)null)
				{
					component3.m_autoDestroyEmpty = false;
				}
			}
		}

		internal static void HoldFullSupport(WearNTear wear)
		{
			if (!(ValheimMembers.GetMaxSupport == null) && !(ValheimMembers.Support == null))
			{
				float num = (float)ValheimMembers.GetMaxSupport.Invoke(wear, null);
				ValheimMembers.Support.SetValue(wear, num);
			}
		}
	}
	internal static class HiddenChestLink
	{
		private const float PairDistance = 0.5f;

		private static readonly Dictionary<Inventory, Container> ByInventory = new Dictionary<Inventory, Container>();

		private static readonly Dictionary<long, Container> ByLink = new Dictionary<long, Container>();

		private static readonly List<Container> Hidden = new List<Container>();

		internal static bool IsHidden(ZNetView view)
		{
			if ((Object)(object)view != (Object)null && view.IsValid() && view.GetZDO() != null)
			{
				return view.GetZDO().GetBool("mb_hidden", false);
			}
			return false;
		}

		internal static void Register(Container container)
		{
			if (!((Object)(object)container == (Object)null))
			{
				Inventory inventory = container.GetInventory();
				if (inventory != null)
				{
					ByInventory[inventory] = container;
				}
			}
		}

		internal static void Unregister(Container container)
		{
			if (!((Object)(object)container == (Object)null))
			{
				Inventory inventory = container.GetInventory();
				if (inventory != null)
				{
					ByInventory.Remove(inventory);
				}
				long num = ReadLink(container);
				if (num != 0L)
				{
					ByLink.Remove(num);
				}
				Hidden.Remove(container);
			}
		}

		internal static Container FindByInventory(Inventory inventory)
		{
			if (inventory == null)
			{
				return null;
			}
			if (!ByInventory.TryGetValue(inventory, out var value))
			{
				return null;
			}
			return value;
		}

		internal static bool HasLink(Turret turret)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = ViewOf(turret);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			ZDO zDO = val.GetZDO();
			if (zDO.GetLong("mb_link", 0L) == 0L)
			{
				return zDO.GetZDOID("mb_chest") != ZDOID.None;
			}
			return true;
		}

		internal static void Bind(Turret turret, Container container)
		{
			ZNetView val = ViewOf(turret);
			ZNetView val2 = (((Object)(object)container != (Object)null) ? ((Component)container).GetComponent<ZNetView>() : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && val2.IsValid())
			{
				long num = val.GetZDO().GetLong("mb_link", 0L);
				if (num == 0L)
				{
					num = val2.GetZDO().GetLong("mb_link", 0L);
				}
				if (num == 0L)
				{
					num = NewLink();
				}
				val.GetZDO().Set("mb_link", num);
				val2.GetZDO().Set("mb_link", num);
				val2.GetZDO().Set("mb_hidden", true);
				Track(container);
				ByLink[num] = container;
				Register(container);
			}
		}

		internal static void TrackLoadedChest(Container container)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHidden(((Component)container).GetComponent<ZNetView>()))
			{
				return;
			}
			Track(container);
			long num = ReadLink(container);
			if (num != 0L)
			{
				ByLink[num] = container;
				return;
			}
			Turret val = NearestTurret(((Component)container).transform.position);
			if ((Object)(object)val != (Object)null && HasLink(val))
			{
				Bind(val, container);
			}
		}

		internal static void TrackLoadedTurret(Turret turret)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!HasLink(turret))
			{
				return;
			}
			long num = ViewOf(turret).GetZDO().GetLong("mb_link", 0L);
			if (num == 0L || !ByLink.ContainsKey(num))
			{
				Container val = NearestHidden(((Component)turret).transform.position);
				if ((Object)(object)val != (Object)null)
				{
					Bind(turret, val);
				}
			}
		}

		internal static Container FindChest(Turret turret)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = ViewOf(turret);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			long num = val.GetZDO().GetLong("mb_link", 0L);
			if (num != 0L && ByLink.TryGetValue(num, out var value) && Object.op_Implicit((Object)(object)value))
			{
				return value;
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ZDOID zDOID = val.GetZDO().GetZDOID("mb_chest");
				if (zDOID != ZDOID.None)
				{
					GameObject val2 = ZNetScene.instance.FindInstance(zDOID);
					if (Object.op_Implicit((Object)(object)val2))
					{
						return val2.GetComponent<Container>();
					}
				}
			}
			if (!HasLink(turret))
			{
				return null;
			}
			Container val3 = NearestHidden(((Component)turret).transform.position);
			if ((Object)(object)val3 == (Object)null)
			{
				return null;
			}
			Bind(turret, val3);
			return val3;
		}

		internal static Turret FindTurret(Container container)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = (((Object)(object)container != (Object)null) ? ((Component)container).GetComponent<ZNetView>() : null);
			if ((Object)(object)val == (Object)null || !val.IsValid() || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			long num = val.GetZDO().GetLong("mb_link", 0L);
			if (num != 0L)
			{
				Turret val2 = NearestTurret(((Component)container).transform.position);
				if ((Object)(object)val2 != (Object)null)
				{
					ZNetView val3 = ViewOf(val2);
					if ((Object)(object)val3 != (Object)null && val3.GetZDO().GetLong("mb_link", 0L) == num)
					{
						return val2;
					}
				}
			}
			GameObject val4 = ZNetScene.instance.FindInstance(val.GetZDO().GetZDOID("mb_turret"));
			if (!Object.op_Implicit((Object)(object)val4))
			{
				return null;
			}
			return val4.GetComponent<Turret>();
		}

		internal static bool CanUse(Container container, Humanoid user)
		{
			if ((Object)(object)container == (Object)null || (Object)(object)user == (Object)null || ValheimMembers.CheckAccess == null)
			{
				return false;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			long num = (((Object)(object)val != (Object)null) ? val.GetPlayerID() : 0);
			return (bool)ValheimMembers.CheckAccess.Invoke(container, new object[1] { num });
		}

		private static void Track(Container container)
		{
			if ((Object)(object)container != (Object)null && !Hidden.Contains(container))
			{
				Hidden.Add(container);
			}
		}

		private static long ReadLink(Container container)
		{
			ZNetView val = (((Object)(object)container != (Object)null) ? ((Component)container).GetComponent<ZNetView>() : null);
			if (!((Object)(object)val != (Object)null) || !val.IsValid())
			{
				return 0L;
			}
			return val.GetZDO().GetLong("mb_link", 0L);
		}

		private static long NewLink()
		{
			long num;
			do
			{
				num = ((long)Random.Range(1, int.MaxValue) << 32) | (uint)Random.Range(1, int.MaxValue);
			}
			while (num == 0L || ByLink.ContainsKey(num));
			return num;
		}

		private static Container NearestHidden(Vector3 position)
		{
			//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)
			Container result = null;
			float num = 0.5f;
			for (int num2 = Hidden.Count - 1; num2 >= 0; num2--)
			{
				Container val = Hidden[num2];
				if (!Object.op_Implicit((Object)(object)val))
				{
					Hidden.RemoveAt(num2);
				}
				else
				{
					float num3 = Vector3.Distance(((Component)val).transform.position, position);
					if (!(num3 >= num))
					{
						num = num3;
						result = val;
					}
				}
			}
			return result;
		}

		private static Turret NearestTurret(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			Collider[] array = Physics.OverlapSphere(position, 0.5f);
			Turret result = null;
			float num = 0.5f;
			for (int i = 0; i < array.Length; i++)
			{
				Turret componentInParent = ((Component)array[i]).GetComponentInParent<Turret>();
				if (!((Object)(object)componentInParent == (Object)null))
				{
					float num2 = Vector3.Distance(((Component)componentInParent).transform.position, position);
					if (!(num2 >= num))
					{
						num = num2;
						result = componentInParent;
					}
				}
			}
			return result;
		}

		private static ZNetView ViewOf(Turret turret)
		{
			if ((Object)(object)turret == (Object)null)
			{
				return null;
			}
			ZNetView component = ((Component)turret).GetComponent<ZNetView>();
			if (!((Object)(object)component != (Object)null) || !component.IsValid())
			{
				return null;
			}
			return component;
		}
	}
	internal static class InventoryAdmission
	{
		internal readonly struct Decision
		{
			internal bool RunOriginal { get; }

			internal bool Result { get; }

			private Decision(bool runOriginal, bool result)
			{
				RunOriginal = runOriginal;
				Result = result;
			}

			internal static Decision Continue()
			{
				return new Decision(runOriginal: true, result: false);
			}

			internal static Decision Stop(bool result)
			{
				return new Decision(runOriginal: false, result);
			}
		}

		internal static bool Apply(Decision decision, ref bool result)
		{
			if (!decision.RunOriginal)
			{
				result = decision.Result;
			}
			return decision.RunOriginal;
		}

		internal static Decision Evaluate(Inventory inventory, ItemData item)
		{
			Container val = HiddenChestLink.FindByInventory(inventory);
			if ((Object)(object)val == (Object)null)
			{
				return Decision.Continue();
			}
			Turret val2 = HiddenChestLink.FindTurret(val);
			if ((Object)(object)val2 != (Object)null && !ItemClassifier.IsAllowed(val2, item))
			{
				return Decision.Stop(result: false);
			}
			return Decision.Continue();
		}
	}
	internal static class ItemClassifier
	{
		internal static ItemCategory Categorize(Turret turret, ItemData item)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			if (item == null || item.m_shared == null)
			{
				return ItemCategory.Other;
			}
			string text = (Object.op_Implicit((Object)(object)item.m_dropPrefab) ? ((Object)item.m_dropPrefab).name : "");
			if (IsBallistaAmmo(turret, text))
			{
				return ItemCategory.Ammo;
			}
			if ((int)item.m_shared.m_itemType != 13)
			{
				return ItemCategory.Other;
			}
			BossTrophyCatalog.Remember();
			if (BossTrophyCatalog.Contains(text) || BossTrophyCatalog.Contains(item.m_shared.m_name))
			{
				return ItemCategory.BossTrophy;
			}
			return ItemCategory.Trophy;
		}

		internal static bool IsAllowed(Turret turret, ItemData item)
		{
			HashSet<string> contents = BallistaRules.ParseList(ModConfig.InventoryContents);
			return BallistaRules.CategoryAllowed(Categorize(turret, item), contents);
		}

		private static bool IsBallistaAmmo(Turret turret, string prefabName)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)turret == (Object)null || turret.m_allowedAmmo == null || prefabName.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < turret.m_allowedAmmo.Count; i++)
			{
				ItemDrop ammo = turret.m_allowedAmmo[i].m_ammo;
				if ((Object)(object)ammo != (Object)null && ((Object)ammo).name == prefabName)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class LinkedChestBreak
	{
		internal static void BreakWithTurret(Turret turret)
		{
			//IL_0039: 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_003f: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)turret).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			ZDOID zDOID = component.GetZDO().GetZDOID("mb_chest");
			if (zDOID == ZDOID.None)
			{
				return;
			}
			GameObject val = ZNetScene.instance.FindInstance(zDOID);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Vector3 val2 = CenterOf(turret);
			ZNetView component2 = val.GetComponent<ZNetView>();
			if ((Object)(object)component2 != (Object)null && component2.IsValid())
			{
				if (!component2.IsOwner())
				{
					component2.ClaimOwnership();
				}
				component2.GetZDO().Set("mb_break", true);
				component2.GetZDO().Set("mb_breakPos", val2);
				component2.GetZDO().SetPosition(val2);
			}
			val.transform.position = val2;
			WearNTear component3 = val.GetComponent<WearNTear>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.Remove(false);
			}
			else
			{
				ZNetScene.instance.Destroy(val);
			}
		}

		internal static void MoveToStoredPosition(WearNTear wear)
		{
			//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)
			//IL_003c: 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)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)wear).GetComponent<ZNetView>();
			if (HiddenChestLink.IsHidden(component))
			{
				ZDO zDO = component.GetZDO();
				if (zDO.GetBool("mb_break", false))
				{
					Vector3 vec = zDO.GetVec3("mb_breakPos", ((Component)wear).transform.position);
					((Component)wear).transform.position = vec;
					zDO.SetPosition(vec);
				}
			}
		}

		internal static void Detach(Container container)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			HiddenChestLink.Unregister(container);
			ZNetView component = ((Component)container).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || component.GetZDO() == null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			ZDOID zDOID = component.GetZDO().GetZDOID("mb_turret");
			if (zDOID == ZDOID.None)
			{
				return;
			}
			GameObject val = ZNetScene.instance.FindInstance(zDOID);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			ZNetView component2 = val.GetComponent<ZNetView>();
			if (!((Object)(object)component2 == (Object)null) && component2.IsValid())
			{
				if (!component2.IsOwner())
				{
					component2.ClaimOwnership();
				}
				component2.GetZDO().Set("mb_chest", ZDOID.None);
				Turret component3 = val.GetComponent<Turret>();
				if ((Object)(object)component3 != (Object)null)
				{
					TurretTargets.Clear(component3);
				}
			}
		}

		private static Vector3 CenterOf(Turret turret)
		{
			//IL_0014: 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_004d: 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)
			Collider[] componentsInChildren = ((Component)turret).GetComponentsInChildren<Collider>();
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				return ((Component)turret).transform.position;
			}
			Bounds bounds = componentsInChildren[0].bounds;
			for (int i = 1; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds);
				}
			}
			return ((Bounds)(ref bounds)).center;
		}
	}
	internal static class PieceAim
	{
		internal static bool TryGetTurret(Player player, out Turret turret)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			turret = null;
			if ((Object)(object)player == (Object)null || (Object)(object)GameCamera.instance == (Object)null || ValheimMembers.PlaceRayMask == null)
			{
				return false;
			}
			int num = (int)ValheimMembers.PlaceRayMask.GetValue(player);
			Transform val = (Transform)((ValheimMembers.Eye != null) ? /*isinst with value type is only supported in some contexts*/: null);
			Vector3 val2 = (((Object)(object)val != (Object)null) ? val.position : ((Component)player).transform.position);
			RaycastHit val3 = default(RaycastHit);
			if (!Physics.Raycast(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward, ref val3, 50f, num))
			{
				return false;
			}
			if (Vector3.Distance(val2, ((RaycastHit)(ref val3)).point) >= player.m_maxPlaceDistance || (Object)(object)((RaycastHit)(ref val3)).collider == (Object)null)
			{
				return false;
			}
			turret = ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<Turret>();
			return (Object)(object)turret != (Object)null;
		}
	}
	internal static class TurretMaintenance
	{
		private const float SyncIntervalSeconds = 0.5f;

		private static readonly Dictionary<int, float> NextSync = new Dictionary<int, float>();

		internal static bool AllowVanillaTargetSearch(Turret turret)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			if (!HiddenChestLink.HasLink(turret))
			{
				return true;
			}
			ZNetView component = ((Component)turret).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return true;
			}
			if (!NextSync.TryGetValue(((Object)turret).GetInstanceID(), out var value) || Time.time >= value)
			{
				NextSync[((Object)turret).GetInstanceID()] = Time.time + 0.5f;
				SyncTargets(turret);
			}
			if (turret.GetAmmo() == 0)
			{
				PullFromChest(turret);
			}
			bool num = component.GetZDO().GetBool("mb_hasTrophies", false);
			List<Character> list = ((ValheimMembers.TargetCharacters != null) ? (ValheimMembers.TargetCharacters.GetValue(turret) as List<Character>) : null);
			if (!num || (list != null && list.Count > 0))
			{
				return true;
			}
			if (ValheimMembers.HaveTarget != null && (bool)ValheimMembers.HaveTarget.GetValue(turret))
			{
				component.InvokeRPC(ZNetView.Everybody, "RPC_SetTarget", new object[1] { ZDOID.None });
			}
			return false;
		}

		private static void SyncTargets(Turret turret)
		{
			Container val = HiddenChestLink.FindChest(turret);
			if (!((Object)(object)val == (Object)null))
			{
				List<SlotItem> slots = ChestInventory.ReadSlots(val, turret);
				bool hasTrophies = !BallistaRules.TargetsEverything(slots);
				List<string> names = BallistaRules.TrophyTargetNames(slots, TurretTargets.MappedNames(turret));
				TurretTargets.Write(turret, names, hasTrophies);
			}
		}

		private static void PullFromChest(Turret turret)
		{
			Container val = HiddenChestLink.FindChest(turret);
			if (!((Object)(object)val == (Object)null))
			{
				List<SlotItem> slots = ChestInventory.ReadSlots(val, turret);
				ChestInventory.PullAmmo(turret, val, slots);
			}
		}
	}
	internal static class TurretTargets
	{
		internal static void Clear(Turret turret)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = (((Object)(object)turret != (Object)null) ? ((Component)turret).GetComponent<ZNetView>() : null);
			if (!((Object)(object)val == (Object)null) && val.IsValid())
			{
				val.GetZDO().Set(ZDOVars.s_targets, 0, false);
				val.GetZDO().Set("mb_hasTrophies", false);
				if (ValheimMembers.ReadTargets != null)
				{
					ValheimMembers.ReadTargets.Invoke(turret, null);
				}
				val.InvokeRPC(ZNetView.Everybody, "RPC_SetTarget", new object[1] { ZDOID.None });
			}
		}

		internal static void Write(Turret turret, IReadOnlyList<string> names, bool hasTrophies)
		{
			ZNetView component = ((Component)turret).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				ZDO zDO = component.GetZDO();
				zDO.Set(ZDOVars.s_targets, names.Count, false);
				zDO.Set("mb_hasTrophies", hasTrophies);
				for (int i = 0; i < names.Count; i++)
				{
					zDO.Set("target" + i, names[i]);
				}
				if (ValheimMembers.ReadTargets != null)
				{
					ValheimMembers.ReadTargets.Invoke(turret, null);
				}
			}
		}

		internal static HashSet<string> MappedNames(Turret turret)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			if (turret.m_configTargets == null)
			{
				return hashSet;
			}
			for (int i = 0; i < turret.m_configTargets.Count; i++)
			{
				ItemDrop item = turret.m_configTargets[i].m_item;
				if ((Object)(object)item != (Object)null && item.m_itemData != null && item.m_itemData.m_shared != null && item.m_itemData.m_shared.m_name != null)
				{
					hashSet.Add(item.m_itemData.m_shared.m_name);
				}
			}
			return hashSet;
		}

		internal static string HoverLine(Turret turret)
		{
			ZNetView component = ((Component)turret).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return null;
			}
			string text = ((!turret.HasAmmo()) ? (turret.m_name + " ($piece_turret_noammo)") : (turret.m_name + " (" + turret.GetAmmo() + " / " + turret.m_maxAmmo + ")"));
			if (!component.GetZDO().GetBool("mb_hasTrophies", false))
			{
				text += " $piece_turret_target $piece_turret_target_everything";
			}
			else
			{
				string text2 = ((ValheimMembers.TargetsText != null) ? (ValheimMembers.TargetsText.GetValue(turret) as string) : null);
				if (!string.IsNullOrEmpty(text2))
				{
					text = text + " $piece_turret_target " + text2;
				}
			}
			text += "\n[<color=yellow><b>$KEY_Use</b></color>] $mb_4";
			return Localization.instance.Localize(text);
		}
	}
	internal static class ValheimMembers
	{
		internal static readonly FieldInfo PlaceRayMask = AccessTools.Field(typeof(Player), "m_placeRayMask");

		internal static readonly FieldInfo Eye = AccessTools.Field(typeof(Character), "m_eye");

		internal static readonly FieldInfo AllAreas = AccessTools.Field(typeof(PrivateArea), "m_allAreas");

		internal static readonly FieldInfo Support = AccessTools.Field(typeof(WearNTear), "m_support");

		internal static readonly FieldInfo TargetCharacters = AccessTools.Field(typeof(Turret), "m_targetCharacters");

		internal static readonly FieldInfo TargetsText = AccessTools.Field(typeof(Turret), "m_targetsText");

		internal static readonly FieldInfo HaveTarget = AccessTools.Field(typeof(Turret), "m_haveTarget");

		internal static readonly MethodInfo ReadTargets = AccessTools.Method(typeof(Turret), "ReadTargets", (Type[])null, (Type[])null);

		internal static readonly MethodInfo GetMaxSupport = AccessTools.Method(typeof(WearNTear), "GetMaxSupport", (Type[])null, (Type[])null);

		internal static readonly MethodInfo CheckAccess = AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null);

		internal static readonly MethodInfo AreaEnabled = AccessTools.Method(typeof(PrivateArea), "IsEnabled", (Type[])null, (Type[])null);

		internal static readonly MethodInfo AreaInside = AccessTools.Method(typeof(PrivateArea), "IsInside", (Type[])null, (Type[])null);
	}
	internal static class WardCoverage
	{
		internal static List<long> OwnerIds(Vector3 point)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			List<long> list = new List<long>();
			List<PrivateArea> list2 = ((ValheimMembers.AllAreas != null) ? (ValheimMembers.AllAreas.GetValue(null) as List<PrivateArea>) : null);
			if (list2 == null || ValheimMembers.AreaEnabled == null || ValheimMembers.AreaInside == null)
			{
				return list;
			}
			for (int i = 0; i < list2.Count; i++)
			{
				PrivateArea val = list2[i];
				if (!((Object)(object)val == (Object)null) && (bool)ValheimMembers.AreaEnabled.Invoke(val, null) && (bool)ValheimMembers.AreaInside.Invoke(val, new object[2] { point, 0f }))
				{
					Piece component = ((Component)val).GetComponent<Piece>();
					if ((Object)(object)component != (Object)null)
					{
						list.Add(component.GetCreator());
					}
				}
			}
			return list;
		}
	}
}

marchiori.utils.dll

Decompiled 18 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using HarmonyLib;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("marchiori.utils")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("marchiori.utils")]
[assembly: AssemblyTitle("marchiori.utils")]
[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 Marchiori.Utils
{
	public static class LanguageFiles
	{
		private const string EnglishFile = "English.csv";

		private static readonly MethodInfo AddWord = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null);

		public static void Apply(Localization localization, string language, string modDirectory, string tokenPrefix)
		{
			if (localization == null || AddWord == null || string.IsNullOrEmpty(modDirectory) || string.IsNullOrEmpty(tokenPrefix))
			{
				return;
			}
			string text = Find(modDirectory, SafeFileName(language) + ".csv");
			if (text == null)
			{
				text = Find(modDirectory, "English.csv");
			}
			if (text == null)
			{
				return;
			}
			foreach (KeyValuePair<int, string> item in Read(text))
			{
				AddWord.Invoke(localization, new object[2]
				{
					tokenPrefix + "_" + item.Key.ToString(CultureInfo.InvariantCulture),
					item.Value
				});
			}
		}

		public static IEnumerable<KeyValuePair<int, string>> Read(string path)
		{
			string[] array = File.ReadAllLines(path, Encoding.UTF8);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length != 0 && text[0] != '#')
				{
					int num = text.IndexOf('=');
					if (num > 0 && int.TryParse(text.Substring(0, num).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
					{
						string value = Unquote(text.Substring(num + 1).Trim());
						yield return new KeyValuePair<int, string>(result, value);
					}
				}
			}
		}

		private static string Unquote(string value)
		{
			if (value.Length >= 2 && value[0] == '"' && value[value.Length - 1] == '"')
			{
				return value.Substring(1, value.Length - 2).Replace("\"\"", "\"");
			}
			return value;
		}

		private static string Find(string root, string fileName)
		{
			if (!Directory.Exists(root))
			{
				return null;
			}
			try
			{
				using IEnumerator<string> enumerator = Directory.EnumerateFiles(root, fileName, SearchOption.AllDirectories).GetEnumerator();
				if (enumerator.MoveNext())
				{
					return enumerator.Current;
				}
			}
			catch (IOException)
			{
				return null;
			}
			catch (UnauthorizedAccessException)
			{
				return null;
			}
			return null;
		}

		private static string SafeFileName(string language)
		{
			if (string.IsNullOrEmpty(language))
			{
				return "English";
			}
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			foreach (char c in invalidFileNameChars)
			{
				language = language.Replace(c.ToString(), "");
			}
			if (language.Length != 0)
			{
				return language;
			}
			return "English";
		}
	}
}