Decompiled source of ScrapSack v1.0.0

plugins/Iron.ScrapSack.dll

Decompiled 3 hours ago
using System;
using System.Collections;
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 System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using ScrapSack.Content;
using ScrapSack.Networking;
using ScrapSack.Patches;
using ScrapSack.Utils;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("DunGen")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")]
[assembly: IgnoresAccessChecksTo("EasyTextEffects")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")]
[assembly: IgnoresAccessChecksTo("Unity.XR.Management")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Iron.ScrapSack")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ScrapSack")]
[assembly: AssemblyTitle("Iron.ScrapSack")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 ScrapSack
{
	[BepInPlugin("Iron.ScrapSack", "ScrapSack", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PLUGIN_GUID = "Iron.ScrapSack";

		public const string PLUGIN_NAME = "ScrapSack";

		public const string PLUGIN_VERSION = "1.0.0";

		private const string LethalLibGuid = "evaisa.lethallib";

		private Harmony _harmony;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				PluginConfig.Init(((BaseUnityPlugin)this).Config);
				SackRules.UseLocal();
				_harmony = new Harmony("Iron.ScrapSack");
				_harmony.PatchAll(typeof(Plugin).Assembly);
				Log.LogInfo((object)"ScrapSack v1.0.0 loaded.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to initialize; the mod is inactive: {arg}");
			}
		}
	}
	internal static class PluginConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<int> Price;

		internal static ConfigEntry<string> ItemName;

		internal static ConfigEntry<int> Capacity;

		internal static ConfigEntry<bool> ResizeSlotUI;

		internal static ConfigEntry<int> SlotsPerRow;

		internal static ConfigEntry<bool> AllowTwoHanded;

		internal static ConfigEntry<string> DeniedItems;

		internal static ConfigEntry<bool> WeightEnabled;

		internal static ConfigEntry<float> WeightMultiplier;

		internal static ConfigEntry<Recoloring> RecolorMode;

		internal static ConfigEntry<string> TintColor;

		internal static ConfigEntry<float> GrabRange;

		internal static ConfigEntry<bool> Tooltip;

		internal static ConfigEntry<bool> DropAll;

		internal static ConfigEntry<bool> EnforceCapacity;

		internal static ConfigEntry<bool> EnforceRestrictions;

		internal static ConfigEntry<bool> EnforceRange;

		private static HashSet<string> _denied = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal static void Init(ConfigFile cfg)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Expected O, but got Unknown
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Expected O, but got Unknown
			Enabled = cfg.Bind<bool>("General", "Enabled", true, "Master switch for the whole mod.");
			Price = cfg.Bind<int>("Shop", "Price", 60, new ConfigDescription("Terminal price of the scrap sack. Needs a game restart.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), Array.Empty<object>()));
			ItemName = cfg.Bind<string>("Shop", "Item Name", "Scrap sack", "Name shown in the terminal and in the HUD. Needs a game restart.");
			Capacity = cfg.Bind<int>("Slots", "Capacity", 4, new ConfigDescription("How many items the sack can hold.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			ResizeSlotUI = cfg.Bind<bool>("Slots", "Resize Inventory UI", true, "Rebuild the bag inventory grid so the number of visible slot squares matches Capacity. The vanilla belt bag's own grid is restored whenever you open a vanilla bag.");
			SlotsPerRow = cfg.Bind<int>("Slots", "Slots Per Row", 4, new ConfigDescription("How many slot squares per row when the UI is rebuilt.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
			AllowTwoHanded = cfg.Bind<bool>("Items", "Allow Two-Handed Scrap", false, "Allow bulky two-handed scrap (paintings, large loot) into the sack. OFF keeps it to one-handed scrap only.");
			DeniedItems = cfg.Bind<string>("Items", "Denied Items", "Apparatus, Body", "Comma-separated item names that never fit, even though they count as scrap. The Apparatus is excluded by default because bagging it interferes with leaving the facility.");
			RebuildDenied();
			DeniedItems.SettingChanged += delegate
			{
				RebuildDenied();
			};
			WeightEnabled = cfg.Bind<bool>("Weight", "Enabled", true, "Make the sack weigh you down by the weight of its contents (vanilla bags are weightless). This is the whole point of the sack: it carries scrap, but you feel it. In multiplayer the host's setting is used, so turning this off only affects lobbies you host.");
			WeightMultiplier = cfg.Bind<float>("Weight", "Multiplier", 1f, new ConfigDescription("Fraction of each stored item's weight that is applied while you carry the sack. In multiplayer the host's value is used.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			RecolorMode = cfg.Bind<Recoloring>("Appearance", "Recolor Mode", Recoloring.SwapRedBlue, "How the vanilla blue bag is turned red. Needs a game restart.\nSwapRedBlue - swap the red and blue channels: blue becomes a clean red and every texture detail and shading survives. Recommended.\nTint - flatly force the base colour to 'Tint Color'. Simpler, but tinting red over a blue texture tends to look muddy.\nOff - leave it looking like the vanilla bag.");
			TintColor = cfg.Bind<string>("Appearance", "Tint Color", "#C81E1E", "Hex colour used by Recolor Mode = Tint. Needs a game restart.");
			GrabRange = cfg.Bind<float>("Misc", "Grab Range", 4f, new ConfigDescription("Max range to grab items into the sack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			Tooltip = cfg.Bind<bool>("Misc", "Tooltips", true, "Show a HUD tip when an item can't be stored (full / not scrap / too bulky).");
			DropAll = cfg.Bind<bool>("Misc", "Empty Bag Action", true, "Right-interact while holding the sack empties it onto the ground.");
			EnforceCapacity = cfg.Bind<bool>("Host", "Enforce Capacity", true, "Server-side capacity check (prevents clients exceeding the host's Capacity).");
			EnforceRestrictions = cfg.Bind<bool>("Host", "Enforce Restrictions", true, "Server-side scrap-only check (prevents clients bagging what the host disallows).");
			EnforceRange = cfg.Bind<bool>("Host", "Enforce Range", true, "Server-side grab-range check.");
			((Dictionary<ConfigDefinition, string>)(typeof(ConfigFile).GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(cfg)))?.Clear();
			cfg.Save();
		}

		private static void RebuildDenied()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			string[] array = DeniedItems.Value.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					hashSet.Add(text);
				}
			}
			_denied = hashSet;
		}

		internal static bool IsDenied(string itemName)
		{
			if (itemName != null)
			{
				return _denied.Contains(itemName);
			}
			return false;
		}
	}
}
namespace ScrapSack.Utils
{
	internal static class NgoUtils
	{
		internal static bool IsRpcServerStage(this NetworkBehaviour self)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			NetworkManager networkManager = self.NetworkManager;
			if ((Object)(object)networkManager == (Object)null || !networkManager.IsListening)
			{
				return false;
			}
			if ((int)self.__rpc_exec_stage != 1)
			{
				return false;
			}
			if (!networkManager.IsServer)
			{
				return networkManager.IsHost;
			}
			return true;
		}
	}
}
namespace ScrapSack.Patches
{
	[HarmonyPatch]
	internal static class BagUiPatch
	{
		private static string _iconPath;

		private static bool _captured;

		private static int _vanillaCount;

		private static Vector2[] _vanillaPositions;

		private static Vector2 _cellSize;

		private static float _xStep;

		private static float _yStep;

		private static Vector2 _center;

		private static bool _layoutIsOurs;

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(BeltBagInventoryUI), "FillSlots")]
		private static void BeforeFillSlots(BeltBagInventoryUI __instance, BeltBagItem __0)
		{
			if (!PluginConfig.Enabled.Value || !PluginConfig.ResizeSlotUI.Value)
			{
				return;
			}
			try
			{
				EnsureSlots(__instance, __0);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Bag UI resize failed (harmless): {arg}");
			}
		}

		private static void EnsureSlots(BeltBagInventoryUI ui, BeltBagItem bag)
		{
			GameObject[] inventorySlots = ui.inventorySlots;
			Image[] inventorySlotIcons = ui.inventorySlotIcons;
			if (inventorySlots == null || inventorySlots.Length == 0 || inventorySlotIcons == null || inventorySlotIcons.Length == 0)
			{
				return;
			}
			CaptureMetrics(inventorySlots);
			bool flag = ScrapSackPatch.Enabled && ScrapSackContent.IsScrapSack((GrabbableObject)(object)bag);
			if (!flag && !_layoutIsOurs)
			{
				return;
			}
			int num = (flag ? Mathf.Clamp(SackRules.Capacity, 1, 100) : _vanillaCount);
			int num2 = inventorySlots.Length;
			if (num2 == num && _layoutIsOurs == flag)
			{
				return;
			}
			GameObject val = inventorySlots[0];
			Transform parent = val.transform.parent;
			if (_iconPath == null)
			{
				_iconPath = RelativePath(inventorySlots[0].transform, ((Component)inventorySlotIcons[0]).transform);
			}
			DisableLayoutGroups(parent);
			GameObject[] array = (GameObject[])(object)new GameObject[num];
			Image[] array2 = (Image[])(object)new Image[num];
			for (int i = 0; i < num; i++)
			{
				GameObject val2;
				Image val3;
				if (i < num2 && (Object)(object)inventorySlots[i] != (Object)null)
				{
					val2 = inventorySlots[i];
					val3 = inventorySlotIcons[i];
				}
				else
				{
					val2 = Object.Instantiate<GameObject>(val, parent);
					((Object)val2).name = $"BeltBagSlot({i})";
					val3 = ResolveIcon(val2);
					RewireClick(ui, val2, i);
				}
				val2.SetActive(true);
				if ((Object)(object)val3 != (Object)null)
				{
					((Behaviour)val3).enabled = false;
				}
				array[i] = val2;
				array2[i] = val3;
			}
			for (int j = num; j < num2; j++)
			{
				if ((Object)(object)inventorySlots[j] != (Object)null)
				{
					inventorySlots[j].SetActive(false);
				}
			}
			ui.inventorySlots = array;
			ui.inventorySlotIcons = array2;
			if (flag)
			{
				LayoutSlots(array);
			}
			else
			{
				RestoreVanillaLayout(array);
			}
			_layoutIsOurs = flag;
		}

		private static void CaptureMetrics(GameObject[] slots)
		{
			//IL_0027: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_0151: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			if (_captured)
			{
				return;
			}
			_vanillaCount = slots.Length;
			_vanillaPositions = (Vector2[])(object)new Vector2[slots.Length];
			RectTransform component = slots[0].GetComponent<RectTransform>();
			Rect rect = component.rect;
			_cellSize = ((Rect)(ref rect)).size;
			float y = component.anchoredPosition.y;
			float num = float.MaxValue;
			float num2 = float.MinValue;
			float num3 = float.MaxValue;
			float num4 = float.MinValue;
			RectTransform val = null;
			RectTransform val2 = null;
			for (int i = 0; i < slots.Length; i++)
			{
				RectTransform component2 = slots[i].GetComponent<RectTransform>();
				Vector2 anchoredPosition = component2.anchoredPosition;
				_vanillaPositions[i] = anchoredPosition;
				if (Mathf.Abs(anchoredPosition.y - y) < 1f)
				{
					if ((Object)(object)val == (Object)null && anchoredPosition.x > component.anchoredPosition.x + 1f)
					{
						val = component2;
					}
				}
				else if ((Object)(object)val2 == (Object)null)
				{
					val2 = component2;
				}
				num = Mathf.Min(num, anchoredPosition.x);
				num2 = Mathf.Max(num2, anchoredPosition.x);
				num3 = Mathf.Min(num3, anchoredPosition.y);
				num4 = Mathf.Max(num4, anchoredPosition.y);
			}
			_xStep = (((Object)(object)val != (Object)null) ? Mathf.Abs(val.anchoredPosition.x - component.anchoredPosition.x) : Mathf.Max(1f, _cellSize.x * 1.15f));
			_yStep = (((Object)(object)val2 != (Object)null) ? Mathf.Abs(val2.anchoredPosition.y - y) : Mathf.Max(1f, _cellSize.y * 1.15f));
			_center = new Vector2((num + num2) * 0.5f, (num3 + num4) * 0.5f);
			_captured = true;
		}

		private static void LayoutSlots(GameObject[] slots)
		{
			//IL_00b0: 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)
			if (!_captured)
			{
				return;
			}
			int num = slots.Length;
			int num2 = Mathf.Max(1, PluginConfig.SlotsPerRow.Value);
			float num3 = (float)(Mathf.CeilToInt((float)num / (float)num2) - 1) * _yStep;
			for (int i = 0; i < num; i++)
			{
				int num4 = i / num2;
				int num5 = i % num2;
				float num6 = (float)(Mathf.Min(num2, num - num4 * num2) - 1) * _xStep;
				float num7 = _center.x - num6 * 0.5f + (float)num5 * _xStep;
				float num8 = _center.y + num3 * 0.5f - (float)num4 * _yStep;
				RectTransform component = slots[i].GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null)
				{
					component.anchoredPosition = new Vector2(num7, num8);
					if (((Vector2)(ref _cellSize)).sqrMagnitude > 0.01f)
					{
						component.sizeDelta = _cellSize;
					}
				}
			}
		}

		private static void RestoreVanillaLayout(GameObject[] slots)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if (!_captured || _vanillaPositions == null)
			{
				return;
			}
			int num = Mathf.Min(slots.Length, _vanillaPositions.Length);
			for (int i = 0; i < num; i++)
			{
				RectTransform component = slots[i].GetComponent<RectTransform>();
				if (!((Object)(object)component == (Object)null))
				{
					component.anchoredPosition = _vanillaPositions[i];
					if (((Vector2)(ref _cellSize)).sqrMagnitude > 0.01f)
					{
						component.sizeDelta = _cellSize;
					}
				}
			}
		}

		private static void DisableLayoutGroups(Transform container)
		{
			LayoutGroup[] components = ((Component)container).GetComponents<LayoutGroup>();
			for (int i = 0; i < components.Length; i++)
			{
				((Behaviour)components[i]).enabled = false;
			}
			ContentSizeFitter[] components2 = ((Component)container).GetComponents<ContentSizeFitter>();
			for (int i = 0; i < components2.Length; i++)
			{
				((Behaviour)components2[i]).enabled = false;
			}
		}

		private static Image ResolveIcon(GameObject slotClone)
		{
			if (string.IsNullOrEmpty(_iconPath))
			{
				return slotClone.GetComponent<Image>();
			}
			Transform val = slotClone.transform.Find(_iconPath);
			if (!((Object)(object)val != (Object)null))
			{
				return slotClone.GetComponentInChildren<Image>(true);
			}
			return ((Component)val).GetComponent<Image>();
		}

		private static void RewireClick(BeltBagInventoryUI ui, GameObject slot, int index)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			Button componentInChildren = slot.GetComponentInChildren<Button>(true);
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				((UnityEventBase)componentInChildren.onClick).RemoveAllListeners();
				((UnityEvent)componentInChildren.onClick).AddListener((UnityAction)delegate
				{
					ui.ClickInventorySlot(index);
				});
			}
		}

		private static string RelativePath(Transform root, Transform child)
		{
			if ((Object)(object)child == (Object)(object)root || (Object)(object)child == (Object)null)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			Transform val = child;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Insert(0, '/');
				}
				stringBuilder.Insert(0, ((Object)val).name);
				val = val.parent;
			}
			return stringBuilder.ToString();
		}
	}
	[HarmonyPatch]
	internal static class ContentPatch
	{
		private static bool _registered;

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		private static void BeforeGameNetworkManagerStart()
		{
			if (_registered)
			{
				return;
			}
			try
			{
				ScrapSackContent.Build();
				if (ScrapSackContent.Ready)
				{
					Items.RegisterShopItem(ScrapSackContent.Item, PluginConfig.Price.Value);
					_registered = true;
					Plugin.Log.LogInfo((object)("\"" + ScrapSackContent.Item.itemName + "\" registered in the shop for " + $"{PluginConfig.Price.Value} credits."));
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to register the scrap sack; it will not be purchasable: {arg}");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		private static void AfterGameNetworkManagerStart()
		{
			GameObject prefab = ScrapSackContent.Prefab;
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || singleton.NetworkConfig == null || singleton.NetworkConfig.Prefabs == null)
			{
				return;
			}
			try
			{
				if (!singleton.NetworkConfig.Prefabs.Contains(prefab))
				{
					singleton.AddNetworkPrefab(prefab);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not add the scrap sack network prefab directly: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	internal static class NetworkPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkManager), "Initialize")]
		private static void AfterNetworkInitialize()
		{
			NamedMessages.Register();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "SetInstanceValuesBackToDefault")]
		private static void OnNetworkTearDown()
		{
			NamedMessages.Unregister();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(StartOfRound), "Start")]
		private static void OnLobbyStart(StartOfRound __instance)
		{
			ScrapSackPatch.Enabled = ((NetworkBehaviour)__instance).IsServer;
			if (((NetworkBehaviour)__instance).IsServer)
			{
				SackRules.UseLocal();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "OnClientConnect")]
		private static void OnClientConnected(StartOfRound __instance, ulong __0)
		{
			if (((NetworkBehaviour)__instance).IsServer)
			{
				NamedMessages.SendHostPresent(new ulong[1] { __0 });
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MenuManager), "Start")]
		private static void OnMainMenu()
		{
			ScrapSackPatch.Enabled = false;
			SackRules.UseLocal();
		}
	}
	[HarmonyPatch]
	internal static class ScrapSackPatch
	{
		internal static bool Enabled;

		private const int ManeaterItemIdA = 123984;

		private const int ManeaterItemIdB = 819501;

		private static bool Active(BeltBagItem bag)
		{
			if (Enabled && PluginConfig.Enabled.Value)
			{
				return ScrapSackContent.IsScrapSack((GrabbableObject)(object)bag);
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(BeltBagItem), "ItemInteractLeftRight")]
		private static bool ItemInteractLeftRight_Prefix(BeltBagItem __instance, bool right)
		{
			if (!Active(__instance))
			{
				return true;
			}
			try
			{
				if (right)
				{
					TryDumpItems(__instance);
				}
				else
				{
					TryGrabItem(__instance);
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"ItemInteractLeftRight_Prefix error: {arg}");
			}
			return false;
		}

		private static void TryGrabItem(BeltBagItem bag)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB playerHeldBy = ((GrabbableObject)bag).playerHeldBy;
			if ((Object)(object)playerHeldBy == (Object)null || (Object)(object)playerHeldBy.currentlyHeldObjectServer != (Object)(object)bag || bag.tryingAddToBag)
			{
				return;
			}
			if (bag.objectsInBag.Count >= SackRules.Capacity)
			{
				Tip("This sack is full!");
				return;
			}
			Transform transform = ((Component)playerHeldBy.gameplayCamera).transform;
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(transform.position, transform.forward, ref val, SackRules.GrabRange, playerHeldBy.interactableObjectsMask) || ((Component)((RaycastHit)(ref val)).collider).gameObject.layer == 8 || !((Component)((RaycastHit)(ref val)).collider).CompareTag("PhysicsProp"))
			{
				return;
			}
			GrabbableObject component = ((Component)((RaycastHit)(ref val)).collider).GetComponent<GrabbableObject>();
			if (CanBePutInBag(bag, component))
			{
				if (IsStorable(component, out var reason))
				{
					bag.TryAddObjectToBag(component);
				}
				else
				{
					Tip(reason);
				}
			}
		}

		private static void TryDumpItems(BeltBagItem bag)
		{
			if (PluginConfig.DropAll.Value && !((Object)(object)((GrabbableObject)bag).playerHeldBy == (Object)null) && !((Object)(object)((GrabbableObject)bag).playerHeldBy.currentlyHeldObjectServer != (Object)(object)bag))
			{
				((MonoBehaviour)bag).StartCoroutine(EmptyBag(bag));
			}
		}

		private static IEnumerator EmptyBag(BeltBagItem bag)
		{
			while (bag.objectsInBag.Count > 0)
			{
				bag.RemoveObjectFromBag(0);
				yield return (object)new WaitForEndOfFrame();
			}
		}

		private static bool CanBePutInBag(BeltBagItem bag, GrabbableObject g)
		{
			if ((Object)(object)g != (Object)null && (Object)(object)g != (Object)(object)bag && !g.isHeld && !g.isHeldByEnemy && (Object)(object)g.itemProperties != (Object)null && g.itemProperties.itemId != 123984)
			{
				return g.itemProperties.itemId != 819501;
			}
			return false;
		}

		private static bool IsStorable(GrabbableObject g, out string reason)
		{
			Item itemProperties = g.itemProperties;
			if (!itemProperties.isScrap)
			{
				reason = "Only scrap goes in this sack!";
				return false;
			}
			if (itemProperties.twoHanded && !SackRules.AllowTwoHanded)
			{
				reason = itemProperties.itemName + " is too bulky for the sack!";
				return false;
			}
			if (SackRules.IsDenied(itemProperties.itemName))
			{
				reason = "Cannot store " + itemProperties.itemName + " in the sack!";
				return false;
			}
			reason = null;
			return true;
		}

		private static void Tip(string message)
		{
			if (PluginConfig.Tooltip.Value && message != null && (Object)(object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.DisplayTip(PluginConfig.ItemName.Value, message, false, false, "LC_Tip1");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BeltBagItem), "TryAddObjectToBagServerRpc")]
		private static bool EnforceOnServer(BeltBagItem __instance, NetworkObjectReference netObjectRef, int playerWhoAdded)
		{
			//IL_00b2: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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)
			if (!Active(__instance))
			{
				return true;
			}
			if (!((NetworkBehaviour)(object)__instance).IsRpcServerStage())
			{
				return true;
			}
			NetworkObject val = default(NetworkObject);
			if (!((NetworkObjectReference)(ref netObjectRef)).TryGet(ref val, (NetworkManager)null))
			{
				return true;
			}
			GrabbableObject component = ((Component)val).GetComponent<GrabbableObject>();
			if (!CanBePutInBag(__instance, component))
			{
				__instance.CancelAddObjectToBagClientRpc(playerWhoAdded);
				return false;
			}
			if (PluginConfig.EnforceCapacity.Value && __instance.objectsInBag.Count >= SackRules.Capacity)
			{
				__instance.CancelAddObjectToBagClientRpc(playerWhoAdded);
				return false;
			}
			if (PluginConfig.EnforceRestrictions.Value && !IsStorable(component, out var _))
			{
				__instance.CancelAddObjectToBagClientRpc(playerWhoAdded);
				return false;
			}
			if (PluginConfig.EnforceRange.Value)
			{
				Vector3 val2 = (((Object)(object)((GrabbableObject)__instance).playerHeldBy != (Object)null) ? ((Component)((GrabbableObject)__instance).playerHeldBy.gameplayCamera).transform.position : Vector3.positiveInfinity);
				if (Vector3.Distance(((Component)component).transform.position, val2) > SackRules.GrabRange + 1f)
				{
					__instance.CancelAddObjectToBagClientRpc(playerWhoAdded);
					return false;
				}
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BeltBagItem), "CancelAddObjectToBagClientRpc")]
		private static void OnServerRefusal(BeltBagItem __instance, int playerWhoAdded)
		{
			if (Active(__instance) && !((Object)(object)StartOfRound.Instance == (Object)null) && !((Object)(object)StartOfRound.Instance.allPlayerScripts[playerWhoAdded] != (Object)(object)GameNetworkManager.Instance.localPlayerController))
			{
				Tip("The host refused that item.");
			}
		}
	}
	[HarmonyPatch]
	internal static class WeightPatch
	{
		private sealed class State
		{
			public PlayerControllerB Player;

			public float Amount;
		}

		private static readonly ConditionalWeakTable<BeltBagItem, State> Applied = new ConditionalWeakTable<BeltBagItem, State>();

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BeltBagItem), "LateUpdate")]
		private static void AfterLateUpdate(BeltBagItem __instance)
		{
			Reconcile(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BeltBagItem), "OnDisable")]
		private static void AfterOnDisable(BeltBagItem __instance)
		{
			Remove(__instance);
		}

		private static bool WeightActive(BeltBagItem bag)
		{
			if (ScrapSackPatch.Enabled && PluginConfig.Enabled.Value && SackRules.WeightEnabled)
			{
				return ScrapSackContent.IsScrapSack((GrabbableObject)(object)bag);
			}
			return false;
		}

		private static float DesiredWeight(BeltBagItem bag)
		{
			if (!WeightActive(bag))
			{
				return 0f;
			}
			if ((Object)(object)((GrabbableObject)bag).playerHeldBy == (Object)null || bag.objectsInBag == null)
			{
				return 0f;
			}
			float weightMultiplier = SackRules.WeightMultiplier;
			float num = 0f;
			foreach (GrabbableObject item in bag.objectsInBag)
			{
				if (!((Object)(object)item == (Object)null) && !((Object)(object)item.itemProperties == (Object)null))
				{
					num += Mathf.Clamp(item.itemProperties.weight - 1f, 0f, 10f);
				}
			}
			return num * weightMultiplier;
		}

		private static void Reconcile(BeltBagItem bag)
		{
			if (!((Object)(object)bag == (Object)null))
			{
				State orCreateValue = Applied.GetOrCreateValue(bag);
				PlayerControllerB val = (WeightActive(bag) ? ((GrabbableObject)bag).playerHeldBy : null);
				float num = (((Object)(object)val != (Object)null) ? DesiredWeight(bag) : 0f);
				if ((Object)(object)orCreateValue.Player != (Object)null && ((Object)(object)orCreateValue.Player != (Object)(object)val || !Mathf.Approximately(orCreateValue.Amount, num)))
				{
					orCreateValue.Player.carryWeight = Mathf.Max(1f, orCreateValue.Player.carryWeight - orCreateValue.Amount);
					orCreateValue.Player = null;
					orCreateValue.Amount = 0f;
				}
				if ((Object)(object)val != (Object)null && num > 0f && (Object)(object)orCreateValue.Player == (Object)null)
				{
					val.carryWeight += num;
					orCreateValue.Player = val;
					orCreateValue.Amount = num;
				}
			}
		}

		private static void Remove(BeltBagItem bag)
		{
			if (!((Object)(object)bag == (Object)null) && Applied.TryGetValue(bag, out var value) && (Object)(object)value.Player != (Object)null)
			{
				value.Player.carryWeight = Mathf.Max(1f, value.Player.carryWeight - value.Amount);
				value.Player = null;
				value.Amount = 0f;
			}
		}
	}
}
namespace ScrapSack.Networking
{
	internal static class NamedMessages
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnHostPresent;

			public static HandleNamedMessageDelegate <1>__OnFixBags;
		}

		private static readonly string Base = "Iron.ScrapSack";

		private static readonly string HostPresentMsg = Base + "|HostPresent";

		private static readonly string FixBagsMsg = Base + "|FixBags";

		internal static void Register()
		{
			//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_0037: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null);
			if (val != null)
			{
				string hostPresentMsg = HostPresentMsg;
				object obj = <>O.<0>__OnHostPresent;
				if (obj == null)
				{
					HandleNamedMessageDelegate val2 = OnHostPresent;
					<>O.<0>__OnHostPresent = val2;
					obj = (object)val2;
				}
				val.RegisterNamedMessageHandler(hostPresentMsg, (HandleNamedMessageDelegate)obj);
				string fixBagsMsg = FixBagsMsg;
				object obj2 = <>O.<1>__OnFixBags;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val3 = OnFixBags;
					<>O.<1>__OnFixBags = val3;
					obj2 = (object)val3;
				}
				val.RegisterNamedMessageHandler(fixBagsMsg, (HandleNamedMessageDelegate)obj2);
			}
		}

		internal static void Unregister()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null);
			if (val != null)
			{
				val.UnregisterNamedMessageHandler(HostPresentMsg);
				val.UnregisterNamedMessageHandler(FixBagsMsg);
			}
		}

		internal static void SendHostPresent(IReadOnlyList<ulong> targets = null)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.IsServer && singleton.CustomMessagingManager != null)
			{
				string text = PluginConfig.DeniedItems.Value ?? string.Empty;
				int num = 14 + FastBufferWriter.GetWriteSize(text, false);
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(num, (Allocator)2, -1);
				int value = PluginConfig.Capacity.Value;
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref value, default(ForPrimitives));
				bool value2 = PluginConfig.AllowTwoHanded.Value;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref value2, default(ForPrimitives));
				value2 = PluginConfig.WeightEnabled.Value;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref value2, default(ForPrimitives));
				float value3 = PluginConfig.WeightMultiplier.Value;
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref value3, default(ForPrimitives));
				value3 = PluginConfig.GrabRange.Value;
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref value3, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
				if (targets == null)
				{
					singleton.CustomMessagingManager.SendNamedMessageToAll(HostPresentMsg, val, (NetworkDelivery)3);
				}
				else
				{
					singleton.CustomMessagingManager.SendNamedMessage(HostPresentMsg, targets, val, (NetworkDelivery)3);
				}
			}
		}

		private static void OnHostPresent(ulong senderId, FastBufferReader reader)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (senderId != 0L)
			{
				return;
			}
			try
			{
				int capacity = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref capacity, default(ForPrimitives));
				bool allowTwoHanded = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref allowTwoHanded, default(ForPrimitives));
				bool weightEnabled = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref weightEnabled, default(ForPrimitives));
				float weightMultiplier = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref weightMultiplier, default(ForPrimitives));
				float grabRange = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref grabRange, default(ForPrimitives));
				string deniedItems = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref deniedItems, false);
				SackRules.Apply(capacity, allowTwoHanded, weightEnabled, weightMultiplier, grabRange, deniedItems);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Could not read the host's settings, using local config: " + ex.Message));
				}
				SackRules.UseLocal();
			}
			ScrapSackPatch.Enabled = true;
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"Host has ScrapSack — sack behaviour enabled (client).");
			}
		}

		internal static void SendFixBags()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.IsServer && singleton.CustomMessagingManager != null)
			{
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(0, (Allocator)2, -1);
				singleton.CustomMessagingManager.SendNamedMessageToAll(FixBagsMsg, val, (NetworkDelivery)3);
			}
		}

		private static void OnFixBags(ulong senderId, FastBufferReader reader)
		{
			if (senderId == 0L && !((Object)(object)StartOfRound.Instance == (Object)null))
			{
				BeltBagItem[] array = Object.FindObjectsByType<BeltBagItem>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				foreach (BeltBagItem obj in array)
				{
					obj.tryingAddToBag = false;
					obj.tryingCheckBag = false;
				}
			}
		}
	}
	internal static class SackRules
	{
		private static HashSet<string> _denied = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal static int Capacity { get; private set; }

		internal static bool AllowTwoHanded { get; private set; }

		internal static bool WeightEnabled { get; private set; }

		internal static float WeightMultiplier { get; private set; }

		internal static float GrabRange { get; private set; }

		internal static bool FromHost { get; private set; }

		internal static string DeniedItemsRaw => PluginConfig.DeniedItems.Value;

		internal static void UseLocal()
		{
			Capacity = PluginConfig.Capacity.Value;
			AllowTwoHanded = PluginConfig.AllowTwoHanded.Value;
			WeightEnabled = PluginConfig.WeightEnabled.Value;
			WeightMultiplier = PluginConfig.WeightMultiplier.Value;
			GrabRange = PluginConfig.GrabRange.Value;
			_denied = ParseDenied(PluginConfig.DeniedItems.Value);
			FromHost = false;
		}

		internal static void Apply(int capacity, bool allowTwoHanded, bool weightEnabled, float weightMultiplier, float grabRange, string deniedItems)
		{
			Capacity = Math.Max(1, capacity);
			AllowTwoHanded = allowTwoHanded;
			WeightEnabled = weightEnabled;
			WeightMultiplier = weightMultiplier;
			GrabRange = grabRange;
			_denied = ParseDenied(deniedItems);
			FromHost = true;
			Plugin.Log.LogInfo((object)($"Using the host's rules: capacity {Capacity}, two-handed {AllowTwoHanded}, " + string.Format("weight {0}, range {1:0.##}.", WeightEnabled ? $"on x{WeightMultiplier:0.##}" : "off", GrabRange)));
		}

		internal static bool IsDenied(string itemName)
		{
			if (itemName != null)
			{
				return _denied.Contains(itemName);
			}
			return false;
		}

		private static HashSet<string> ParseDenied(string raw)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			if (string.IsNullOrEmpty(raw))
			{
				return hashSet;
			}
			string[] array = raw.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					hashSet.Add(text);
				}
			}
			return hashSet;
		}
	}
}
namespace ScrapSack.Content
{
	internal enum Recoloring
	{
		Off,
		Tint,
		SwapRedBlue
	}
	internal static class Recolor
	{
		private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor");

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		private static readonly int BaseColorMapId = Shader.PropertyToID("_BaseColorMap");

		private static readonly int MainTexId = Shader.PropertyToID("_MainTex");

		private static readonly Dictionary<Texture, Texture2D> Converted = new Dictionary<Texture, Texture2D>();

		internal static void Apply(GameObject prefab, Item item)
		{
			Recoloring value = PluginConfig.RecolorMode.Value;
			if (value == Recoloring.Off)
			{
				return;
			}
			try
			{
				Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val in componentsInChildren)
				{
					Material[] sharedMaterials = val.sharedMaterials;
					if (sharedMaterials != null && sharedMaterials.Length != 0)
					{
						Material[] array = (Material[])(object)new Material[sharedMaterials.Length];
						for (int j = 0; j < sharedMaterials.Length; j++)
						{
							array[j] = (((Object)(object)sharedMaterials[j] != (Object)null) ? Recoloured(sharedMaterials[j], value) : null);
						}
						val.sharedMaterials = array;
					}
				}
				if (item.materialVariants != null)
				{
					Material[] array2 = (Material[])(object)new Material[item.materialVariants.Length];
					for (int k = 0; k < array2.Length; k++)
					{
						Material val2 = item.materialVariants[k];
						array2[k] = (((Object)(object)val2 != (Object)null) ? Recoloured(val2, value) : null);
					}
					item.materialVariants = array2;
				}
				item.itemIcon = RecolouredSprite(item.itemIcon, value);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Recolouring failed; the sack will look like a vanilla belt bag: {arg}");
			}
		}

		private static Material Recoloured(Material source, Recoloring mode)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//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)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(source)
			{
				name = ((Object)source).name + " (ScrapSack)",
				hideFlags = (HideFlags)61
			};
			if (mode == Recoloring.Tint)
			{
				Color c = ParseColor(PluginConfig.TintColor.Value);
				SetIfPresent(val, BaseColorId, c);
				SetIfPresent(val, ColorId, c);
				return val;
			}
			SwapColorProperty(val, BaseColorId);
			SwapColorProperty(val, ColorId);
			SwapTextureProperty(val, BaseColorMapId);
			SwapTextureProperty(val, MainTexId);
			return val;
		}

		private static void SetIfPresent(Material m, int prop, Color c)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			if (m.HasProperty(prop))
			{
				Color color = m.GetColor(prop);
				m.SetColor(prop, new Color(c.r, c.g, c.b, color.a));
			}
		}

		private static void SwapColorProperty(Material m, int prop)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			if (m.HasProperty(prop))
			{
				Color color = m.GetColor(prop);
				m.SetColor(prop, new Color(color.b, color.g, color.r, color.a));
			}
		}

		private static void SwapTextureProperty(Material m, int prop)
		{
			if (!m.HasProperty(prop))
			{
				return;
			}
			Texture texture = m.GetTexture(prop);
			if (!((Object)(object)texture == (Object)null))
			{
				Texture2D val = Transform(texture, SwapRedBlue);
				if ((Object)(object)val != (Object)null)
				{
					m.SetTexture(prop, (Texture)(object)val);
				}
			}
		}

		private static Sprite RecolouredSprite(Sprite icon, Recoloring mode)
		{
			//IL_003b: 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)
			//IL_002d: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)icon == (Object)null || (Object)(object)icon.texture == (Object)null)
			{
				return icon;
			}
			try
			{
				Color tint = (Color)((mode == Recoloring.Tint) ? ParseColor(PluginConfig.TintColor.Value) : default(Color));
				Texture2D val = ((mode == Recoloring.Tint) ? Transform((Texture)(object)icon.texture, (Color32 p) => TintPixel(p, tint)) : Transform((Texture)(object)icon.texture, SwapRedBlue));
				if ((Object)(object)val == (Object)null)
				{
					return icon;
				}
				Rect rect = icon.rect;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor((((Rect)(ref rect)).width > 0f) ? (icon.pivot.x / ((Rect)(ref rect)).width) : 0.5f, (((Rect)(ref rect)).height > 0f) ? (icon.pivot.y / ((Rect)(ref rect)).height) : 0.5f);
				Sprite obj = Sprite.Create(val, rect, val2, icon.pixelsPerUnit);
				((Object)obj).name = ((Object)icon).name + " (ScrapSack)";
				((Object)obj).hideFlags = (HideFlags)61;
				return obj;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not recolour the item icon (harmless): " + ex.Message));
				return icon;
			}
		}

		private static Color32 SwapRedBlue(Color32 p)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			byte r = p.r;
			p.r = p.b;
			p.b = r;
			return p;
		}

		private static Color32 TintPixel(Color32 p, Color tint)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_002d: 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)
			return new Color32((byte)((float)(int)p.r * tint.r), (byte)((float)(int)p.g * tint.g), (byte)((float)(int)p.b * tint.b), p.a);
		}

		private static Texture2D Transform(Texture source, Func<Color32, Color32> transform)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			if (Converted.TryGetValue(source, out var value))
			{
				return value;
			}
			Texture2D val = null;
			RenderTexture val2 = null;
			RenderTexture active = RenderTexture.active;
			try
			{
				val2 = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
				Graphics.Blit(source, val2);
				RenderTexture.active = val2;
				val = new Texture2D(source.width, source.height, (TextureFormat)4, true, false);
				val.ReadPixels(new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), 0, 0);
				Color32[] pixels = val.GetPixels32();
				for (int i = 0; i < pixels.Length; i++)
				{
					pixels[i] = transform(pixels[i]);
				}
				val.SetPixels32(pixels);
				val.Apply();
				((Object)val).name = ((Object)source).name + " (ScrapSack)";
				((Texture)val).wrapMode = source.wrapMode;
				((Texture)val).filterMode = source.filterMode;
				((Texture)val).anisoLevel = source.anisoLevel;
				((Object)val).hideFlags = (HideFlags)61;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not convert texture '" + ((Object)source).name + "' (left as-is): " + ex.Message));
				val = null;
			}
			finally
			{
				RenderTexture.active = active;
				if ((Object)(object)val2 != (Object)null)
				{
					RenderTexture.ReleaseTemporary(val2);
				}
			}
			Converted[source] = val;
			return val;
		}

		private static Color ParseColor(string hex)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			if (!string.IsNullOrEmpty(hex) && ColorUtility.TryParseHtmlString(hex.Trim(), ref result))
			{
				return result;
			}
			Plugin.Log.LogWarning((object)("Could not parse Tint Color '" + hex + "'; falling back to red."));
			return Color.red;
		}
	}
	internal static class ScrapSackContent
	{
		private const int ScrapSackItemId = 771001;

		internal static Item Item { get; private set; }

		internal static GameObject Prefab { get; private set; }

		internal static bool Ready
		{
			get
			{
				if ((Object)(object)Item != (Object)null)
				{
					return (Object)(object)Prefab != (Object)null;
				}
				return false;
			}
		}

		internal static bool IsScrapSack(GrabbableObject grabbable)
		{
			if ((Object)(object)grabbable != (Object)null && (Object)(object)Item != (Object)null)
			{
				return grabbable.itemProperties == Item;
			}
			return false;
		}

		internal static void Build()
		{
			if (Ready)
			{
				return;
			}
			GameObject val = FindVanillaBeltBagPrefab();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)("Could not find the vanilla belt bag prefab; the scrap sack will not be available. " + $"Scanned {CountNetworkPrefabs()} network prefabs. This usually means the game " + "version is not the one this build targets (v81)."));
				return;
			}
			Prefab = NetworkPrefabs.CloneNetworkPrefab(val, "ScrapSack");
			if ((Object)(object)Prefab == (Object)null)
			{
				Plugin.Log.LogError((object)"Cloning the belt bag prefab failed; the scrap sack will not be available.");
				return;
			}
			BeltBagItem component = Prefab.GetComponent<BeltBagItem>();
			if ((Object)(object)component == (Object)null || (Object)(object)((GrabbableObject)component).itemProperties == (Object)null)
			{
				Plugin.Log.LogError((object)"The cloned prefab has no BeltBagItem/itemProperties; aborting.");
				Prefab = null;
				return;
			}
			Item = Object.Instantiate<Item>(((GrabbableObject)component).itemProperties);
			((Object)Item).name = "ScrapSackItemData";
			Item.itemName = PluginConfig.ItemName.Value;
			Item.itemId = 771001;
			Item.isScrap = false;
			Item.creditsWorth = PluginConfig.Price.Value;
			Item.spawnPrefab = Prefab;
			((Object)Item).hideFlags = (HideFlags)61;
			((GrabbableObject)component).itemProperties = Item;
			Recolor.Apply(Prefab, Item);
			Plugin.Log.LogInfo((object)("Built \"" + Item.itemName + "\" from the vanilla belt bag " + $"(hash {Prefab.GetComponent<NetworkObject>()?.GlobalObjectIdHash})."));
		}

		private static GameObject FindVanillaBeltBagPrefab()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton != (Object)null && singleton.NetworkConfig != null && singleton.NetworkConfig.Prefabs != null)
			{
				foreach (NetworkPrefab prefab in singleton.NetworkConfig.Prefabs.Prefabs)
				{
					GameObject val = prefab?.Prefab;
					if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<BeltBagItem>() != (Object)null)
					{
						return val;
					}
				}
			}
			Item[] array = Resources.FindObjectsOfTypeAll<Item>();
			foreach (Item val2 in array)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.spawnPrefab != (Object)null && (Object)(object)val2.spawnPrefab.GetComponent<BeltBagItem>() != (Object)null)
				{
					return val2.spawnPrefab;
				}
			}
			return null;
		}

		private static int CountNetworkPrefabs()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			object obj;
			if (singleton == null)
			{
				obj = null;
			}
			else
			{
				NetworkConfig networkConfig = singleton.NetworkConfig;
				if (networkConfig == null)
				{
					obj = null;
				}
				else
				{
					NetworkPrefabs prefabs = networkConfig.Prefabs;
					obj = ((prefabs != null) ? prefabs.Prefabs : null);
				}
			}
			return ((IReadOnlyCollection<NetworkPrefab>)obj)?.Count ?? (-1);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}