Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ScrapSack v1.0.0
plugins/Iron.ScrapSack.dll
Decompiled 3 hours agousing 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) { } } }