Decompiled source of ScrapperPlus v1.0.1

BepInEx/plugins/ScrapperPlus/ScrapperPlus.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RoR2;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ScrapperPlus
{
	internal sealed class HoldRepeatButton : MonoBehaviour, IPointerDownHandler, IEventSystemHandler, IPointerUpHandler, IPointerExitHandler
	{
		private const float InitialDelay = 0.5f;

		private const float Interval = 0.2f;

		private Action step;

		private Func<bool> canStep;

		private Action onPressStart;

		private Action onRelease;

		private bool holding;

		private float nextStepTime;

		internal void Configure(Action step, Func<bool> canStep, Action onPressStart, Action onRelease)
		{
			this.step = step;
			this.canStep = canStep;
			this.onPressStart = onPressStart;
			this.onRelease = onRelease;
		}

		public void OnPointerDown(PointerEventData eventData)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)eventData.button == 0 && CanStepNow())
			{
				onPressStart?.Invoke();
				Step();
				holding = true;
				nextStepTime = Time.unscaledTime + 0.5f;
			}
		}

		public void OnPointerUp(PointerEventData eventData)
		{
			Stop(notify: true);
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			Stop(notify: true);
		}

		private void Update()
		{
			if (!holding)
			{
				return;
			}
			if (!CanStepNow())
			{
				Stop(notify: true);
			}
			else if (!(Time.unscaledTime < nextStepTime))
			{
				Step();
				nextStepTime = Time.unscaledTime + 0.2f;
				if (!CanStepNow())
				{
					Stop(notify: true);
				}
			}
		}

		private void Stop(bool notify)
		{
			if (holding)
			{
				holding = false;
				if (notify)
				{
					onRelease?.Invoke();
				}
			}
		}

		private bool CanStepNow()
		{
			if (canStep != null)
			{
				return canStep();
			}
			return true;
		}

		private void Step()
		{
			step?.Invoke();
		}

		private void OnDisable()
		{
			Stop(notify: true);
		}

		private void OnApplicationFocus(bool hasFocus)
		{
			if (!hasFocus)
			{
				Stop(notify: true);
			}
		}
	}
	[BepInPlugin("ScrapperPlus", "ScrapperPlus", "1.0.1")]
	public sealed class ScrapperPlusPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "ScrapperPlus";

		public const string PluginName = "ScrapperPlus";

		public const string PluginVersion = "1.0.1";

		internal const int VanillaScrapLimit = 10;

		private Harmony harmony;

		public static ScrapperPlusPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		public static ConfigEntry<int> LastCount { get; private set; }

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_00b5: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			LastCount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "LastCount", 1, new ConfigDescription("上次使用的分解数量。范围 1-10,打开收割机面板时读取。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
			harmony = new Harmony("ScrapperPlus");
			try
			{
				harmony.PatchAll();
				Log.LogInfo((object)("ScrapperPlus 1.0.1 loaded. Game=" + Application.version));
			}
			catch (Exception ex)
			{
				Log.LogError((object)("ScrapperPlus patch failure: " + ex));
			}
			GameObject val = new GameObject("ScrapperPlusWatcher")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<ScrapperPanelWatcher>();
		}

		private void OnDestroy()
		{
			try
			{
				Harmony obj = harmony;
				if (obj != null)
				{
					obj.UnpatchSelf();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("Harmony unpatch failed: " + ex));
				}
			}
		}
	}
	internal static class ScrapperCountNetwork
	{
		private readonly struct Key : IEquatable<Key>
		{
			public readonly int PickerId;

			public readonly uint ParticipantId;

			public Key(int pickerId, uint participantId)
			{
				PickerId = pickerId;
				ParticipantId = participantId;
			}

			public bool Equals(Key other)
			{
				if (PickerId == other.PickerId)
				{
					return ParticipantId == other.ParticipantId;
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is Key other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (PickerId * 397) ^ (int)ParticipantId;
			}
		}

		public const byte MessageId = 83;

		public const uint Magic = 1397771313u;

		public const byte ProtocolVersion = 1;

		private static readonly Dictionary<Key, int> Pending = new Dictionary<Key, int>();

		public static void SetPending(PickupPickerController picker, int count)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)picker))
			{
				NetworkUIPromptController component = ((Component)picker).GetComponent<NetworkUIPromptController>();
				CharacterMaster val = (Object.op_Implicit((Object)(object)component) ? component.currentParticipantMaster : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					int value = Mathf.Clamp(count, 1, 10);
					Dictionary<Key, int> pending = Pending;
					int instanceID = ((Object)picker).GetInstanceID();
					NetworkInstanceId netId = ((NetworkBehaviour)val).netId;
					pending[new Key(instanceID, ((NetworkInstanceId)(ref netId)).Value)] = value;
				}
			}
		}

		public static bool TryTakePending(PickupPickerController picker, out int count)
		{
			//IL_003a: 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)
			count = 10;
			if (!Object.op_Implicit((Object)(object)picker))
			{
				return false;
			}
			NetworkUIPromptController component = ((Component)picker).GetComponent<NetworkUIPromptController>();
			CharacterMaster val = (Object.op_Implicit((Object)(object)component) ? component.currentParticipantMaster : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			int instanceID = ((Object)picker).GetInstanceID();
			NetworkInstanceId netId = ((NetworkBehaviour)val).netId;
			Key key = new Key(instanceID, ((NetworkInstanceId)(ref netId)).Value);
			if (!Pending.TryGetValue(key, out var value))
			{
				return false;
			}
			Pending.Remove(key);
			count = Mathf.Clamp(value, 1, 10);
			return true;
		}

		public static void ClearPicker(PickupPickerController picker)
		{
			if (!Object.op_Implicit((Object)(object)picker))
			{
				return;
			}
			int instanceID = ((Object)picker).GetInstanceID();
			List<Key> list = null;
			foreach (Key key in Pending.Keys)
			{
				if (key.PickerId == instanceID)
				{
					if (list == null)
					{
						list = new List<Key>();
					}
					list.Add(key);
				}
			}
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					Pending.Remove(list[i]);
				}
			}
		}

		public static void Send(PickupPickerController picker, int count)
		{
			if (!Object.op_Implicit((Object)(object)picker))
			{
				return;
			}
			int count2 = Mathf.Clamp(count, 1, 10);
			if (NetworkServer.active)
			{
				SetPending(picker, count2);
			}
			if (!NetworkClient.active)
			{
				return;
			}
			NetworkUIPromptController component = ((Component)picker).GetComponent<NetworkUIPromptController>();
			if (Object.op_Implicit((Object)(object)component) && component.isDisplaying)
			{
				NetworkWriter val = component.BeginMessageToServer();
				if (val != null)
				{
					WriteCount(val, count2);
					component.FinishMessageToServer(val);
				}
			}
		}

		public static void WriteCount(NetworkWriter writer, int count)
		{
			writer.Write((byte)83);
			writer.Write(1397771313u);
			writer.Write((byte)1);
			writer.Write(Mathf.Clamp(count, 1, 10));
		}

		public static bool TryReadCount(NetworkReader reader, out int count)
		{
			count = 10;
			uint num = reader.ReadUInt32();
			byte b = reader.ReadByte();
			int num2 = reader.ReadInt32();
			if (num != 1397771313 || b != 1)
			{
				return false;
			}
			count = Mathf.Clamp(num2, 1, 10);
			return true;
		}
	}
	internal sealed class ScrapperPanelWatcher : MonoBehaviour
	{
		private const float ScanInterval = 0.1f;

		private float nextScan;

		private PickupPickerPanel attached;

		private void Update()
		{
			if ((Object.op_Implicit((Object)(object)attached) && ((Component)attached).gameObject.activeInHierarchy) || Time.unscaledTime < nextScan)
			{
				return;
			}
			nextScan = Time.unscaledTime + 0.1f;
			try
			{
				attached = FindScrapperPanel();
				if (Object.op_Implicit((Object)(object)attached) && !Object.op_Implicit((Object)(object)((Component)attached).GetComponent<ScrapperPlusPanel>()))
				{
					((Component)attached).gameObject.AddComponent<ScrapperPlusPanel>().Attach(attached);
				}
			}
			catch (Exception ex)
			{
				ScrapperPlusPlugin.Log.LogWarning((object)("ScrapperPlus: panel scan failed: " + ex));
			}
		}

		private static PickupPickerPanel FindScrapperPanel()
		{
			PickupPickerPanel[] array = Object.FindObjectsOfType<PickupPickerPanel>(true);
			foreach (PickupPickerPanel val in array)
			{
				if (Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.activeInHierarchy && IsScrapperPicker(val.pickerController))
				{
					return val;
				}
			}
			return null;
		}

		private static bool IsScrapperPicker(PickupPickerController picker)
		{
			if (!Object.op_Implicit((Object)(object)picker))
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)((Component)picker).GetComponent<ScrapperController>()) && !Object.op_Implicit((Object)(object)((Component)picker).GetComponentInParent<ScrapperController>()))
			{
				return Object.op_Implicit((Object)(object)((Component)picker).GetComponentInChildren<ScrapperController>(true));
			}
			return true;
		}
	}
	public sealed class ScrapperPlusPanel : MonoBehaviour
	{
		private const string ControlName = "ScrapperPlusCountControl";

		private const float Gap = 12f;

		private const float OuterBorderThickness = 1.5f;

		private const float BorderGap = 2.5f;

		private const float InnerBorderThickness = 3f;

		private static readonly Color BorderColor = new Color(0.89f, 0.89f, 0.896f, 1f);

		private static readonly Color TextColor = Color.white;

		private static readonly Color DisabledTextColor = new Color(0.5f, 0.5f, 0.5f, 1f);

		private PickupPickerPanel panel;

		private PickupPickerController picker;

		private RectTransform cancelRect;

		private RectTransform root;

		private Button minusButton;

		private Button plusButton;

		private TextMeshProUGUI numberText;

		private TextMeshProUGUI minusText;

		private TextMeshProUGUI plusText;

		private int count = 1;

		private int lastBuildCheckFrame;

		private int buildAttempts;

		private bool warnedNoCancel;

		private bool built;

		private bool siblingMode;

		private bool dirty;

		private readonly List<GameObject> spawned = new List<GameObject>();

		private static Sprite whiteSprite;

		internal void Attach(PickupPickerPanel panel)
		{
			this.panel = panel;
		}

		private void Update()
		{
			if (!Object.op_Implicit((Object)(object)panel))
			{
				return;
			}
			bool activeInHierarchy = ((Component)panel).gameObject.activeInHierarchy;
			picker = panel.pickerController;
			if (!activeInHierarchy || !IsScrapperPicker(picker))
			{
				if (built)
				{
					Teardown();
				}
			}
			else if (!built && Time.frameCount - lastBuildCheckFrame >= 2)
			{
				lastBuildCheckFrame = Time.frameCount;
				TryBuild();
			}
		}

		private void LateUpdate()
		{
			if (built)
			{
				PositionRoot();
			}
		}

		private void OnDestroy()
		{
			Teardown();
		}

		private static bool IsScrapperPicker(PickupPickerController picker)
		{
			if (!Object.op_Implicit((Object)(object)picker))
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)((Component)picker).GetComponent<ScrapperController>()) && !Object.op_Implicit((Object)(object)((Component)picker).GetComponentInParent<ScrapperController>()))
			{
				return Object.op_Implicit((Object)(object)((Component)picker).GetComponentInChildren<ScrapperController>(true));
			}
			return true;
		}

		private void TryBuild()
		{
			cancelRect = FindCancel();
			if (!Object.op_Implicit((Object)(object)cancelRect))
			{
				buildAttempts++;
				if (buildAttempts > 300 && !warnedNoCancel)
				{
					warnedNoCancel = true;
					ScrapperPlusPlugin.Log.LogWarning((object)"ScrapperPlus: scrapper panel is open but CancelButton was not found.");
				}
			}
			else if (!Build())
			{
				cancelRect = null;
			}
			else
			{
				built = true;
				buildAttempts = 0;
				Refresh();
				PositionRoot();
				SendCountToServer();
				ScrapperPlusPlugin.Log.LogInfo((object)$"ScrapperPlus: control ready, count={count}");
			}
		}

		private RectTransform FindCancel()
		{
			Transform val = ((Component)panel).transform.Find("MainPanel/Juice/CancelButton");
			if (Object.op_Implicit((Object)(object)val))
			{
				return (RectTransform)(object)((val is RectTransform) ? val : null);
			}
			Transform[] componentsInChildren = ((Component)panel).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (string.Equals(((Object)componentsInChildren[i]).name, "CancelButton", StringComparison.OrdinalIgnoreCase))
				{
					Transform obj = componentsInChildren[i];
					return (RectTransform)(object)((obj is RectTransform) ? obj : null);
				}
			}
			return null;
		}

		private static Sprite WhiteSprite()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)whiteSprite))
			{
				Texture2D whiteTexture = Texture2D.whiteTexture;
				whiteSprite = Sprite.Create(whiteTexture, new Rect(0f, 0f, (float)((Texture)whiteTexture).width, (float)((Texture)whiteTexture).height), new Vector2(0.5f, 0.5f));
			}
			return whiteSprite;
		}

		private bool Build()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ScrapperPlusCountControl", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image),
				typeof(Button)
			});
			root = val.GetComponent<RectTransform>();
			siblingMode = IsSafeToParentNextToCancel();
			((Transform)root).SetParent(siblingMode ? ((Transform)cancelRect).parent : ((Component)panel).transform, false);
			((Transform)root).SetAsLastSibling();
			root.anchorMin = Vector2.zero;
			root.anchorMax = Vector2.zero;
			root.pivot = new Vector2(0f, 0.5f);
			((Transform)root).localScale = Vector3.one;
			((Transform)root).localRotation = Quaternion.identity;
			root.sizeDelta = ControlSize();
			root.anchoredPosition = Vector2.zero;
			spawned.Add(val);
			val.AddComponent<LayoutElement>().ignoreLayout = true;
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(0f, 0f, 0f, 0f);
			((Graphic)component).raycastTarget = true;
			component.sprite = WhiteSprite();
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).transition = (Transition)0;
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)component2).navigation = navigation;
			CreateBorderFrame("Outer", 0f, 1.5f);
			CreateBorderFrame("Inner", 4f, 3f);
			TextMeshProUGUI val2 = FindText(((Component)cancelRect).gameObject);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				Teardown();
				return false;
			}
			count = Mathf.Clamp(ScrapperPlusPlugin.LastCount.Value, 1, 10);
			numberText = CreateLabel((Transform)(object)root, "ScrapperPlusNumber", count.ToString(), val2, 1f / 3f, 2f / 3f);
			minusButton = CreateZone("ScrapperPlusMinus", "-", 0f, 1f / 3f, val2, out minusText, -1);
			plusButton = CreateZone("ScrapperPlusPlus", "+", 2f / 3f, 1f, val2, out plusText, 1);
			Canvas.ForceUpdateCanvases();
			return true;
		}

		private bool IsSafeToParentNextToCancel()
		{
			Transform parent = ((Transform)cancelRect).parent;
			if (!Object.op_Implicit((Object)(object)parent))
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)((Component)parent).GetComponent<RectMask2D>()) || Object.op_Implicit((Object)(object)((Component)parent).GetComponent<Mask>()))
			{
				ScrapperPlusPlugin.Log.LogInfo((object)"ScrapperPlus: cancel container is masked; using absolute positioning.");
				return false;
			}
			return true;
		}

		private void CreateBorderFrame(string tag, float inset, float thickness)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			float num = inset + thickness;
			CreateBorderStrip("ScrapperPlusBorder" + tag + "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(inset, 0f - num), new Vector2(0f - inset, 0f - inset));
			CreateBorderStrip("ScrapperPlusBorder" + tag + "Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(inset, inset), new Vector2(0f - inset, num));
			CreateBorderStrip("ScrapperPlusBorder" + tag + "Left", new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(inset, num), new Vector2(num, 0f - num));
			CreateBorderStrip("ScrapperPlusBorder" + tag + "Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(0f - num, num), new Vector2(0f - inset, 0f - num));
		}

		private void CreateBorderStrip(string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			spawned.Add(val);
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)root, false);
			component.anchorMin = anchorMin;
			component.anchorMax = anchorMax;
			component.offsetMin = offsetMin;
			component.offsetMax = offsetMax;
			((Transform)component).localScale = Vector3.one;
			Image component2 = val.GetComponent<Image>();
			component2.sprite = WhiteSprite();
			((Graphic)component2).color = BorderColor;
			((Graphic)component2).raycastTarget = false;
		}

		private Vector2 ControlSize()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)cancelRect))
			{
				return new Vector2(200f, 48f);
			}
			Rect rect = cancelRect.rect;
			float num = ((Rect)(ref rect)).width;
			rect = cancelRect.rect;
			float num2 = ((Rect)(ref rect)).height;
			if (num < 80f || num > 600f)
			{
				num = 200f;
			}
			if (num2 < 20f || num2 > 200f)
			{
				num2 = 48f;
			}
			return new Vector2(num, num2);
		}

		private static TextMeshProUGUI FindText(GameObject rootObject)
		{
			TextMeshProUGUI[] componentsInChildren = rootObject.GetComponentsInChildren<TextMeshProUGUI>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren[i]) && ((TMP_Text)componentsInChildren[i]).text == "Cancel")
				{
					return componentsInChildren[i];
				}
			}
			for (int j = 0; j < componentsInChildren.Length; j++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren[j]) && string.Equals(((Object)((Component)componentsInChildren[j]).gameObject).name, "Text", StringComparison.OrdinalIgnoreCase))
				{
					return componentsInChildren[j];
				}
			}
			if (componentsInChildren.Length == 0)
			{
				return null;
			}
			return componentsInChildren[0];
		}

		private static void PlaceLabel(RectTransform rect, float anchorMinX, float anchorMaxX)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(anchorMinX, 0f);
			rect.anchorMax = new Vector2(anchorMaxX, 1f);
			rect.offsetMin = Vector2.zero;
			rect.offsetMax = Vector2.zero;
			((Transform)rect).localScale = Vector3.one;
		}

		private TextMeshProUGUI CreateLabel(Transform parent, string name, string text, TextMeshProUGUI template, float anchorMinX, float anchorMaxX)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, parent, false);
			((Object)val).name = name;
			spawned.Add(val);
			PlaceLabel(val.GetComponent<RectTransform>(), anchorMinX, anchorMaxX);
			LanguageTextMeshController[] componentsInChildren = val.GetComponentsInChildren<LanguageTextMeshController>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Behaviour)componentsInChildren[i]).enabled = false;
				Object.Destroy((Object)(object)componentsInChildren[i]);
			}
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return null;
			}
			((TMP_Text)component).text = text;
			((Graphic)component).color = TextColor;
			((TMP_Text)component).alignment = (TextAlignmentOptions)514;
			((Graphic)component).raycastTarget = false;
			((TMP_Text)component).enableWordWrapping = false;
			((TMP_Text)component).overflowMode = (TextOverflowModes)0;
			return component;
		}

		private Button CreateZone(string name, string symbol, float anchorMinX, float anchorMaxX, TextMeshProUGUI template, out TextMeshProUGUI label, int delta)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image),
				typeof(Button)
			});
			spawned.Add(val);
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)root, false);
			component.anchorMin = new Vector2(anchorMinX, 0f);
			component.anchorMax = new Vector2(anchorMaxX, 1f);
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			((Transform)component).localScale = Vector3.one;
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = new Color(0f, 0f, 0f, 0f);
			((Graphic)component2).raycastTarget = true;
			Button component3 = val.GetComponent<Button>();
			((Selectable)component3).targetGraphic = (Graphic)(object)component2;
			((Selectable)component3).transition = (Transition)0;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)component3).navigation = navigation;
			val.AddComponent<HoldRepeatButton>().Configure(delegate
			{
				Adjust(delta);
			}, () => (delta >= 0) ? (count < 10) : (count > 1), PlayClick, Commit);
			label = CreateLabel(val.transform, name + "Label", symbol, template, 0f, 1f);
			return component3;
		}

		private static void PlayClick()
		{
			if (Object.op_Implicit((Object)(object)RoR2Application.instance))
			{
				Util.PlaySound("Play_UI_menuClick", ((Component)RoR2Application.instance).gameObject);
			}
		}

		private void Adjust(int delta)
		{
			int num = Mathf.Clamp(count + delta, 1, 10);
			if (num != count)
			{
				count = num;
				dirty = true;
				Refresh();
			}
		}

		private void Commit()
		{
			PersistConfig();
			SendCountToServer();
		}

		private void PersistConfig()
		{
			if (!dirty)
			{
				return;
			}
			dirty = false;
			ScrapperPlusPlugin.LastCount.Value = count;
			try
			{
				((BaseUnityPlugin)ScrapperPlusPlugin.Instance).Config.Save();
			}
			catch (Exception ex)
			{
				ScrapperPlusPlugin.Log.LogWarning((object)("ScrapperPlus: failed to save config: " + ex));
			}
		}

		private void SendCountToServer()
		{
			if (Object.op_Implicit((Object)(object)picker))
			{
				ScrapperCountNetwork.Send(picker, count);
			}
		}

		private void Refresh()
		{
			//IL_0029: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)numberText))
			{
				((TMP_Text)numberText).text = count.ToString();
				((Graphic)numberText).color = TextColor;
			}
			if (Object.op_Implicit((Object)(object)minusButton))
			{
				((Selectable)minusButton).interactable = count > 1;
			}
			if (Object.op_Implicit((Object)(object)plusButton))
			{
				((Selectable)plusButton).interactable = count < 10;
			}
			if (Object.op_Implicit((Object)(object)minusText))
			{
				((Graphic)minusText).color = ((count > 1) ? TextColor : DisabledTextColor);
			}
			if (Object.op_Implicit((Object)(object)plusText))
			{
				((Graphic)plusText).color = ((count < 10) ? TextColor : DisabledTextColor);
			}
		}

		private void PositionRoot()
		{
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)root) || !Object.op_Implicit((Object)(object)cancelRect))
			{
				return;
			}
			Rect rect;
			if (siblingMode)
			{
				if ((Object)(object)((Transform)root).parent != (Object)(object)((Transform)cancelRect).parent)
				{
					((Transform)root).SetParent(((Transform)cancelRect).parent, false);
				}
				root.anchorMin = cancelRect.anchorMin;
				root.anchorMax = cancelRect.anchorMax;
				root.pivot = cancelRect.pivot;
				((Transform)root).localScale = Vector3.one;
				((Transform)root).localRotation = Quaternion.identity;
				bool flag = !Mathf.Approximately(cancelRect.anchorMin.x, cancelRect.anchorMax.x);
				RectTransform obj = root;
				float num;
				if (!flag)
				{
					rect = cancelRect.rect;
					num = ((Rect)(ref rect)).width;
				}
				else
				{
					num = cancelRect.sizeDelta.x;
				}
				rect = cancelRect.rect;
				obj.sizeDelta = new Vector2(num, ((Rect)(ref rect)).height);
				RectTransform obj2 = root;
				Vector2 anchoredPosition = cancelRect.anchoredPosition;
				rect = cancelRect.rect;
				obj2.anchoredPosition = anchoredPosition + new Vector2(((Rect)(ref rect)).width + 12f, 0f);
				return;
			}
			Vector2 val = ControlSize();
			if (Mathf.Abs(root.sizeDelta.x - val.x) > 0.5f || Mathf.Abs(root.sizeDelta.y - val.y) > 0.5f)
			{
				root.sizeDelta = val;
			}
			RectTransform obj3 = cancelRect;
			rect = cancelRect.rect;
			float xMax = ((Rect)(ref rect)).xMax;
			rect = cancelRect.rect;
			float yMin = ((Rect)(ref rect)).yMin;
			rect = cancelRect.rect;
			Vector3 val2 = ((Transform)obj3).TransformPoint(new Vector3(xMax, (yMin + ((Rect)(ref rect)).yMax) * 0.5f, 0f));
			Vector3 val3 = ((Transform)cancelRect).TransformDirection(Vector3.right);
			if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f)
			{
				val3 = Vector3.right;
			}
			Vector3 val4 = ((Transform)cancelRect).TransformVector(Vector3.right);
			float magnitude = ((Vector3)(ref val4)).magnitude;
			Vector3 val5 = val2 + ((Vector3)(ref val3)).normalized * (12f * magnitude);
			val4 = ((Transform)root).position - val5;
			if (((Vector3)(ref val4)).sqrMagnitude > 0.01f)
			{
				((Transform)root).position = val5;
			}
		}

		private void Teardown()
		{
			PersistConfig();
			for (int i = 0; i < spawned.Count; i++)
			{
				if (Object.op_Implicit((Object)(object)spawned[i]))
				{
					Object.Destroy((Object)(object)spawned[i]);
				}
			}
			spawned.Clear();
			root = null;
			cancelRect = null;
			numberText = null;
			minusText = null;
			plusText = null;
			minusButton = null;
			plusButton = null;
			built = false;
			buildAttempts = 0;
			warnedNoCancel = false;
		}
	}
}
namespace ScrapperPlus.Patches
{
	internal static class ScrapperPatchHelpers
	{
		public static bool IsScrapperPicker(PickupPickerController picker)
		{
			if (!Object.op_Implicit((Object)(object)picker))
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)((Component)picker).GetComponent<ScrapperController>()))
			{
				return Object.op_Implicit((Object)(object)((Component)picker).GetComponentInParent<ScrapperController>());
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PickupPickerController), "HandleClientMessage")]
	internal static class HandleClientMessagePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(PickupPickerController __instance, NetworkReader reader)
		{
			if (!ScrapperPatchHelpers.IsScrapperPicker(__instance))
			{
				return true;
			}
			try
			{
				byte b = reader.ReadByte();
				switch (b)
				{
				case 0:
				{
					int num = reader.ReadInt32();
					__instance.SubmitChoice(num);
					break;
				}
				case 1:
				{
					NetworkUIPromptController component = ((Component)__instance).GetComponent<NetworkUIPromptController>();
					if (Object.op_Implicit((Object)(object)component))
					{
						component.SetParticipantMaster((CharacterMaster)null);
					}
					ScrapperCountNetwork.ClearPicker(__instance);
					break;
				}
				case 83:
				{
					if (ScrapperCountNetwork.TryReadCount(reader, out var count))
					{
						ScrapperCountNetwork.SetPending(__instance, count);
					}
					break;
				}
				default:
					ScrapperPlusPlugin.Log.LogDebug((object)("ScrapperPlus: ignored unknown picker message id " + b));
					break;
				}
			}
			catch (Exception ex)
			{
				ScrapperPlusPlugin.Log.LogWarning((object)("ScrapperPlus: HandleClientMessage failed: " + ex));
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PickupPickerController), "HandlePickupSelected")]
	internal static class HandlePickupSelectedPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PickupPickerController __instance)
		{
			if (ScrapperPatchHelpers.IsScrapperPicker(__instance))
			{
				ScrapperCountNetwork.ClearPicker(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(ScrapperController), "BeginScrapping", new Type[] { typeof(UniquePickup) })]
	internal static class BeginScrappingPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ScrapperController __instance)
		{
			if (NetworkServer.active)
			{
				int count;
				int num = (ScrapperCountNetwork.TryTakePending(__instance.pickupPickerController, out count) ? count : 10);
				__instance.maxItemsToScrapAtATime = Mathf.Clamp(num, 1, 10);
			}
		}

		[HarmonyPostfix]
		private static void Postfix(ScrapperController __instance)
		{
			if (NetworkServer.active)
			{
				__instance.maxItemsToScrapAtATime = 10;
			}
		}
	}
}