Decompiled source of OmniTool v1.12.4

OmniTool.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace OmniTool;

[BepInPlugin("com.burks.omnitool", "Omni Tool", "1.12.3")]
public class OmniToolPlugin : BaseUnityPlugin
{
	internal class Rule
	{
		public string Name;

		public bool Destroy;

		public int Keep;
	}

	public const string GUID = "com.burks.omnitool";

	public const string NAME = "Omni Tool";

	public const string VERSION = "1.12.3";

	public const string PrefabName = "BurksOmniTool";

	internal static ManualLogSource Log;

	internal static ConfigEntry<string> Recipe;

	internal static ConfigEntry<string> Station;

	internal static ConfigEntry<int> StationLevel;

	internal static ConfigEntry<float> Reach;

	internal static ConfigEntry<float> SourceReach;

	internal static ConfigEntry<KeyCode> MatchKey;

	internal static bool Headless;

	private static GameObject _prefab;

	private static GameObject _holder;

	private static Sprite _icon;

	internal static readonly FieldRef<Humanoid, ItemData> RightItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_rightItem");

	internal static ConfigEntry<string> WorkbenchName;

	internal static ConfigEntry<bool> ConfirmDestroy;

	internal static ConfigEntry<KeyCode> ModeKey;

	internal static ConfigEntry<string> RulesCfg;

	internal static ConfigEntry<bool> AutoApply;

	internal static ConfigEntry<bool> AutoDrops;

	internal static ConfigEntry<bool> EnTransfer;

	internal static ConfigEntry<bool> EnAssistant;

	internal static ConfigEntry<bool> EnRepair;

	internal static ConfigEntry<bool> EnDestroy;

	internal static ConfigEntry<bool> EnBuild;

	internal static ConfigEntry<KeyCode> BuildMenuMod;

	internal static ConfigEntry<float> BuildHoldTime;

	internal static PieceTable HammerTable;

	internal static SharedData ToolShared;

	internal static readonly Mode[] Order = new Mode[5]
	{
		Mode.Build,
		Mode.Transfer,
		Mode.Assistant,
		Mode.Repair,
		Mode.Destroy
	};

	internal static ConfigEntry<bool> UseMenu;

	internal static ConfigEntry<bool> MenuCloseOnSelect;

	internal static ConfigEntry<float> AdvRange;

	internal static ConfigEntry<bool> RequireWorkbench;

	internal static ConfigEntry<bool> OnlyPlayerBuilt;

	internal static ConfigEntry<bool> NoPersonalSources;

	internal static ConfigEntry<bool> RespectFavorites;

	internal static ConfigEntry<float> MenuScale;

	internal static Mode CurMode = Mode.Transfer;

	private static bool _qsLooked;

	private static MethodInfo _qsGetConfig;

	private static MethodInfo _qsIsFav;

	private static readonly MethodInfo SetPlaceModeM = AccessTools.Method(typeof(Player), "SetPlaceMode", (Type[])null, (Type[])null);

	private static bool _healedLogged;

	private static float _removeDownAt = -1f;

	private static bool _removeUsed;

	internal static bool BypassRemoveBlock;

	private static readonly MethodInfo RemovePieceM = AccessTools.Method(typeof(Player), "RemovePiece", (Type[])null, (Type[])null);

	private static float _nextUse;

	private static Container _source;

	internal static readonly FieldRef<Container, ZNetView> NView = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview");

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

	private static readonly FieldRef<Container, Inventory> CInv = AccessTools.FieldRefAccess<Container, Inventory>("m_inventory");

	private static readonly FieldRef<Container, bool> CLoading = AccessTools.FieldRefAccess<Container, bool>("m_loading");

	private static readonly FieldRef<Container, bool> CInUse = AccessTools.FieldRefAccess<Container, bool>("m_inUse");

	private static readonly FieldRef<Container, uint> CRev = AccessTools.FieldRefAccess<Container, uint>("m_lastRevision");

	private static readonly FieldRef<Player, int> RemoveMask = AccessTools.FieldRefAccess<Player, int>("m_removeRayMask");

	private static readonly MethodInfo CheckCanRemove = AccessTools.Method(typeof(Player), "CheckCanRemovePiece", (Type[])null, (Type[])null);

	private static Piece _pendingPiece;

	private static float _pendingUntil;

	internal static readonly List<Rule> Rules = new List<Rule>();

	private static bool _showPanel;

	private static float _autoAt = -1f;

	private Rect _win = new Rect(-1f, 160f, 360f, 560f);

	private Vector2 _scrollRules;

	private Vector2 _scrollAdd;

	private void Awake()
	{
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Invalid comparison between Unknown and I4
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Recipe = ((BaseUnityPlugin)this).Config.Bind<string>("Crafting", "Recipe", "Wood:10,Stone:1", "Cost to craft, as Item:Amount pairs (prefab names).");
		if (Recipe.Value.Replace(" ", "") == "Wood:10,Resin:5,Copper:3")
		{
			Recipe.Value = "Wood:10,Stone:1";
		}
		Station = ((BaseUnityPlugin)this).Config.Bind<string>("Crafting", "Station", "piece_workbench", "Crafting station prefab (piece_workbench, forge, ...).");
		StationLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Crafting", "StationLevel", 1, "Station level needed.");
		Reach = ((BaseUnityPlugin)this).Config.Bind<float>("Use", "Reach", 20f, "How far away (metres) you can point at a chest.");
		SourceReach = ((BaseUnityPlugin)this).Config.Bind<float>("Use", "SourceMaxDistance", 80f, "How far the source chest may be from you when you move items out of it.");
		if (Mathf.Approximately(SourceReach.Value, 60f))
		{
			SourceReach.Value = 80f;
		}
		MatchKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Use", "OnlyMatchingKey", (KeyCode)304, "Hold this while left-clicking to move only items the target chest already has.");
		BindTools(((BaseUnityPlugin)this).Config);
		Model.Bind(((BaseUnityPlugin)this).Config);
		Headless = (int)SystemInfo.graphicsDeviceType == 4;
		Harmony val = new Harmony("com.burks.omnitool");
		val.PatchAll(Assembly.GetExecutingAssembly());
		try
		{
			int num = val.GetPatchedMethods().Count((MethodBase m) => m.DeclaringType == typeof(ZInput));
			Log.LogInfo((object)("Key blocking hooked into " + num + " input checks."));
		}
		catch
		{
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Omni Tool 1.12.3 loaded.");
	}

	internal static GameObject Prefab(Func<string, GameObject> find)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		if ((Object)(object)_prefab != (Object)null)
		{
			return _prefab;
		}
		GameObject val = find("Hammer");
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		_holder = new GameObject("burks_omnitool_holder");
		Object.DontDestroyOnLoad((Object)(object)_holder);
		_holder.SetActive(false);
		_prefab = Object.Instantiate<GameObject>(val, _holder.transform);
		((Object)_prefab).name = "BurksOmniTool";
		SharedData shared = _prefab.GetComponent<ItemDrop>().m_itemData.m_shared;
		shared.m_name = "Omni Tool";
		shared.m_description = "Middle-click opens the mode menu: Build, Transfer, Inventory Assistant, Repair, Destroy. Repair and Destroy need you to stand at a workbench and only reach as far as its build radius.";
		HammerTable = shared.m_buildPieces;
		ToolShared = shared;
		shared.m_buildPieces = null;
		shared.m_useDurability = false;
		shared.m_canBeReparied = false;
		shared.m_weight = 1f;
		Sprite val2 = Icon();
		if ((Object)(object)val2 != (Object)null)
		{
			shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 };
		}
		if (!Headless)
		{
			try
			{
				Model.Swap(_prefab);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Model swap failed, keeping the hammer look: " + ex.Message));
			}
		}
		Log.LogInfo((object)"Omni Tool item created.");
		return _prefab;
	}

	private static Sprite Icon()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Expected O, but got Unknown
		//IL_007a: 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)
		if ((Object)(object)_icon != (Object)null || Headless)
		{
			return _icon;
		}
		try
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("OmniTool.item.png");
			if (stream == null)
			{
				return null;
			}
			MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			((Object)val).hideFlags = (HideFlags)32;
			ImageConversion.LoadImage(val, memoryStream.ToArray());
			_icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			((Object)_icon).hideFlags = (HideFlags)32;
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Icon failed: " + ex.Message));
		}
		return _icon;
	}

	internal static void Register(ObjectDB db)
	{
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: 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_025c: Expected O, but got Unknown
		if ((Object)(object)db == (Object)null || db.m_items == null || db.m_items.Count == 0)
		{
			return;
		}
		GameObject val = Prefab((string n) => db.GetItemPrefab(n));
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if (!db.m_items.Contains(val))
		{
			db.m_items.Add(val);
			AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null).Invoke(db, null);
		}
		if (db.m_recipes.Any((Recipe r) => (Object)(object)r != (Object)null && (Object)(object)r.m_item != (Object)null && ((Object)r.m_item).name == "BurksOmniTool"))
		{
			return;
		}
		Recipe val2 = ScriptableObject.CreateInstance<Recipe>();
		((Object)val2).name = "Recipe_BurksOmniTool";
		val2.m_item = val.GetComponent<ItemDrop>();
		val2.m_amount = 1;
		val2.m_enabled = true;
		val2.m_minStationLevel = Mathf.Max(1, StationLevel.Value);
		GameObject val3 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(Station.Value) : null);
		val2.m_craftingStation = (((Object)(object)val3 != (Object)null) ? val3.GetComponent<CraftingStation>() : null);
		if ((Object)(object)val2.m_craftingStation == (Object)null)
		{
			Recipe val4 = ((IEnumerable<Recipe>)db.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => (Object)(object)r != (Object)null && (Object)(object)r.m_craftingStation != (Object)null && ((Object)r.m_craftingStation).name == Station.Value));
			if ((Object)(object)val4 != (Object)null)
			{
				val2.m_craftingStation = val4.m_craftingStation;
			}
		}
		List<Requirement> list = new List<Requirement>();
		string[] array = (Recipe.Value ?? "").Split(',');
		foreach (string text in array)
		{
			string[] array2 = text.Split(':');
			if (array2.Length == 2)
			{
				GameObject itemPrefab = db.GetItemPrefab(array2[0].Trim());
				if ((Object)(object)itemPrefab == (Object)null || !int.TryParse(array2[1].Trim(), out var result))
				{
					Log.LogWarning((object)("Recipe item not found: " + text));
					continue;
				}
				list.Add(new Requirement
				{
					m_resItem = itemPrefab.GetComponent<ItemDrop>(),
					m_amount = result,
					m_recover = true
				});
			}
		}
		val2.m_resources = list.ToArray();
		db.m_recipes.Add(val2);
	}

	internal static bool Holding(Humanoid h)
	{
		if ((Object)(object)h == (Object)null)
		{
			return false;
		}
		ItemData val = RightItem.Invoke(h);
		if (val == null || !((Object)(object)val.m_dropPrefab != (Object)null) || !(((Object)val.m_dropPrefab).name == "BurksOmniTool"))
		{
			if (val != null && val.m_shared != null)
			{
				return val.m_shared.m_name == "Omni Tool";
			}
			return false;
		}
		return true;
	}

	private static void BindTools(ConfigFile c)
	{
		ModeKey = c.Bind<KeyCode>("Use", "SwitchModeKey", (KeyCode)0, "Optional keyboard key that also switches mode (middle-click always does).");
		Undupe.Bind(c);
		UseMenu = c.Bind<bool>("Menu", "MiddleClickOpensMenu", true, "Middle-click opens the mode menu. Off = middle-click just switches to the next mode (also used automatically on a gamepad).");
		MenuCloseOnSelect = c.Bind<bool>("Menu", "CloseOnSelect", true, "Close the menu when you click a mode.");
		RespectFavorites = c.Bind<bool>("AdvancedTransfer", "LeaveQuickStackFavorites", true, "Never take items out of your inventory that Quick Stack - Store - Sort - Trash - Restock marks as favorited (favorited items or favorited slots). Also applies to the Inventory Assistant.");
		AdvRange = c.Bind<float>("AdvancedTransfer", "Range", 80f, "How far (metres) presets look for source and target storages.");
		if (Mathf.Approximately(AdvRange.Value, 40f))
		{
			AdvRange.Value = 80f;
		}
		RequireWorkbench = c.Bind<bool>("Transfer", "OnlyInWorkbenchAreas", true, "Transfers (basic and Advanced) only work while you stand in a workbench's area, and only on storages inside a workbench's area.");
		OnlyPlayerBuilt = c.Bind<bool>("Transfer", "OnlyPlayerBuiltStorage", true, "Ignore storage that wasn't built by a player (dungeon and world chests).");
		NoPersonalSources = c.Bind<bool>("Transfer", "NeverEmptyPersonalChests", true, "Never take items out of personal (private) chests.");
		MenuScale = c.Bind<float>("Menu", "Scale", 1f, "Size of the menu (1 = fits about 72% of the screen width).");
		EnTransfer = c.Bind<bool>("Modes", "Transfer", true, "Chest-to-chest transfer mode.");
		EnAssistant = c.Bind<bool>("Modes", "InventoryAssistant", true, "Inventory assistant mode.");
		EnRepair = c.Bind<bool>("Modes", "Repair", true, "Distant area repair mode.");
		EnDestroy = c.Bind<bool>("Modes", "Destroy", true, "Distant destroy mode.");
		EnBuild = c.Bind<bool>("Modes", "Build", true, "Build mode: the tool works like the hammer.");
		BuildHoldTime = c.Bind<float>("Menu", "BuildModeHoldSeconds", 0.4f, "In Build mode a quick middle-click removes a piece; holding it this long opens the Omni menu instead.");
		BuildMenuMod = c.Bind<KeyCode>("Menu", "BuildModeMenuModifier", (KeyCode)308, "In Build mode middle-click removes pieces like the hammer; hold this key while middle-clicking to open the Omni menu instead.");
		WorkbenchName = c.Bind<string>("Workbench", "StationName", "$piece_workbench", "Station you must stand in range of for Repair and Destroy. Its build radius is how far the tool reaches.");
		ConfirmDestroy = c.Bind<bool>("Workbench", "ConfirmDestroy", true, "Destroy needs two left-clicks on the same piece within 3 seconds.");
		RulesCfg = c.Bind<string>("Assistant", "Rules", "", "Saved rules (edited from the panel). Format: $item_name=drop:keep;...");
		AutoApply = c.Bind<bool>("Assistant", "AutoApplyOnPickup", false, "Run the rules after you pick something up, while the Omni Tool is in your inventory.");
		AutoDrops = c.Bind<bool>("Assistant", "AutoApplyDropsToo", false, "Let automatic runs drop items as well as destroy them. Off by default because dropped items can get picked back up.");
		LoadRules();
	}

	internal static void Say(string s)
	{
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, s, 0, (Sprite)null, false);
		}
	}

	internal static bool IsFavorited(Player p, ItemData it)
	{
		if ((Object)(object)p == (Object)null || it == null || RespectFavorites == null || !RespectFavorites.Value)
		{
			return false;
		}
		if (!_qsLooked)
		{
			_qsLooked = true;
			Type type = AccessTools.TypeByName("QuickStackStore.UserConfig");
			if (type != null)
			{
				_qsGetConfig = AccessTools.Method(type, "GetPlayerConfig", new Type[1] { typeof(long) }, (Type[])null);
				_qsIsFav = AccessTools.Method(type, "IsItemNameOrSlotFavorited", new Type[1] { typeof(ItemData) }, (Type[])null);
			}
			Log.LogInfo((object)((_qsGetConfig != null && _qsIsFav != null) ? "Quick Stack favorites found - favorited items/slots will be left alone." : "Quick Stack favorites not found (mod not installed or changed)."));
		}
		if (_qsGetConfig == null || _qsIsFav == null)
		{
			return false;
		}
		try
		{
			object obj = _qsGetConfig.Invoke(null, new object[1] { p.GetPlayerID() });
			return obj != null && (bool)_qsIsFav.Invoke(obj, new object[1] { it });
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Quick Stack favorite check: " + ex.Message));
			_qsIsFav = null;
			return false;
		}
	}

	internal static string Loc(string s)
	{
		try
		{
			return Localization.instance.Localize(s);
		}
		catch
		{
			return s;
		}
	}

	private static bool Enabled(Mode m)
	{
		return m switch
		{
			Mode.Transfer => EnTransfer.Value, 
			Mode.Assistant => EnAssistant.Value, 
			Mode.Repair => EnRepair.Value, 
			Mode.Build => EnBuild.Value, 
			_ => EnDestroy.Value, 
		};
	}

	internal static string ModeHelp(Mode m)
	{
		return m switch
		{
			Mode.Transfer => "Transfer: right-click source chest, left-click target chest", 
			Mode.Assistant => "Inventory Assistant: left-click opens rules, right-click runs them", 
			Mode.Repair => "Repair: left-click repairs everything in this workbench's area, right-click repairs what you aim at", 
			Mode.Build => "Build: works like the hammer. Hold middle-click to open this menu", 
			_ => "Destroy: left-click a piece in this workbench's area" + (ConfirmDestroy.Value ? " (twice to confirm)" : ""), 
		};
	}

	internal static void CycleMode()
	{
		int num = Array.IndexOf(Order, CurMode);
		for (int i = 1; i <= Order.Length; i++)
		{
			Mode mode = Order[(num + i) % Order.Length];
			if (Enabled(mode))
			{
				CurMode = mode;
				break;
			}
		}
		_pendingPiece = null;
		ApplyBuild();
		Say("Omni Tool - " + ModeHelp(CurMode));
	}

	internal static void ApplyBuild()
	{
		if (ToolShared == null)
		{
			return;
		}
		PieceTable val = ((CurMode == Mode.Build && Enabled(Mode.Build)) ? HammerTable : null);
		ToolShared.m_buildPieces = val;
		Player localPlayer = Player.m_localPlayer;
		ItemData val2 = (((Object)(object)localPlayer != (Object)null) ? RightItem.Invoke((Humanoid)(object)localPlayer) : null);
		if (val2 != null && val2.m_shared != null && Holding((Humanoid)(object)localPlayer))
		{
			val2.m_shared.m_buildPieces = val;
		}
		Log.LogInfo((object)("[Mode] " + CurMode.ToString() + (((Object)(object)val != (Object)null) ? " (hammer on)" : "")));
		if (!((Object)(object)localPlayer != (Object)null) || !Holding((Humanoid)(object)localPlayer) || !(SetPlaceModeM != null))
		{
			return;
		}
		try
		{
			SetPlaceModeM.Invoke(localPlayer, new object[1] { val });
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("SetPlaceMode: " + ex.Message));
		}
	}

	internal static void SetMode(Mode m)
	{
		if (CurMode != m)
		{
			CurMode = m;
			_pendingPiece = null;
			ApplyBuild();
			Say("Omni Tool - " + ModeHelp(CurMode));
		}
	}

	internal static ItemData HeldItem(Player p)
	{
		return RightItem.Invoke((Humanoid)(object)p);
	}

	internal static void KeepPlaceModeInStep(Player p)
	{
		if (!Holding((Humanoid)(object)p) || SetPlaceModeM == null)
		{
			return;
		}
		ItemData val = RightItem.Invoke((Humanoid)(object)p);
		if (val == null || val.m_shared == null)
		{
			return;
		}
		if (CurMode == Mode.Build && Enabled(Mode.Build) && (Object)(object)HammerTable != (Object)null)
		{
			if ((Object)(object)val.m_shared.m_buildPieces == (Object)null)
			{
				val.m_shared.m_buildPieces = HammerTable;
			}
			if (!((Character)p).InPlaceMode())
			{
				SetPlaceModeM.Invoke(p, new object[1] { HammerTable });
			}
			return;
		}
		if ((Object)(object)val.m_shared.m_buildPieces != (Object)null)
		{
			val.m_shared.m_buildPieces = null;
		}
		if (((Character)p).InPlaceMode())
		{
			SetPlaceModeM.Invoke(p, new object[1]);
			if (!_healedLogged)
			{
				_healedLogged = true;
				Log.LogInfo((object)"[Mode] build mode was still on outside Build mode - turned it off.");
			}
		}
	}

	private static void BuildMiddleClick(Player p)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		if (!Holding((Humanoid)(object)p) || CurMode != Mode.Build || !Enabled(Mode.Build) || OmniUI.Busy)
		{
			_removeDownAt = -1f;
			return;
		}
		bool button = ZInput.GetButton("Remove");
		if (button && _removeDownAt < 0f)
		{
			_removeDownAt = Time.time;
			_removeUsed = ZInput.GetKey(BuildMenuMod.Value, false);
		}
		if (button && !_removeUsed && Time.time - _removeDownAt >= BuildHoldTime.Value)
		{
			_removeUsed = true;
			OmniMenu.Show();
		}
		if (button || !(_removeDownAt >= 0f))
		{
			return;
		}
		if (!_removeUsed && RemovePieceM != null)
		{
			BypassRemoveBlock = true;
			try
			{
				RemovePieceM.Invoke(p, null);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Remove: " + ex.Message));
			}
			BypassRemoveBlock = false;
		}
		_removeDownAt = -1f;
	}

	internal static void ModeButton()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		if (CurMode != Mode.Build || !Enabled(Mode.Build) || ZInput.GetKey(BuildMenuMod.Value, false))
		{
			if (UseMenu.Value && !ZInput.IsGamepadActive())
			{
				OmniMenu.Show();
			}
			else
			{
				CycleMode();
			}
		}
	}

	internal static void Primary()
	{
		if (!(Time.time < _nextUse))
		{
			_nextUse = Time.time + 0.15f;
			if (!Enabled(CurMode))
			{
				CycleModeSilently();
			}
			switch (CurMode)
			{
			case Mode.Transfer:
				Transfer();
				break;
			case Mode.Assistant:
				OpenAssistant();
				break;
			case Mode.Repair:
				RepairArea();
				break;
			case Mode.Destroy:
				DestroyAimed();
				break;
			case Mode.Build:
				break;
			}
		}
	}

	internal static void Secondary()
	{
		if (!(Time.time < _nextUse))
		{
			_nextUse = Time.time + 0.15f;
			if (!Enabled(CurMode))
			{
				CycleModeSilently();
			}
			switch (CurMode)
			{
			case Mode.Transfer:
				PickSource();
				break;
			case Mode.Assistant:
			{
				int num = ApplyRules(automatic: false);
				Say((num > 0) ? ("Assistant: cleared " + num + " items.") : "Assistant: nothing over its limit.");
				break;
			}
			case Mode.Repair:
				RepairAimed();
				break;
			case Mode.Destroy:
				_pendingPiece = null;
				Say(ModeHelp(Mode.Destroy));
				break;
			case Mode.Build:
				break;
			}
		}
	}

	private static void CycleModeSilently()
	{
		Mode[] order = Order;
		foreach (Mode mode in order)
		{
			if (Enabled(mode))
			{
				CurMode = mode;
				ApplyBuild();
				break;
			}
		}
	}

	private static Container AimedChest()
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer != (Object)null)
		{
			GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject();
			Container val = (((Object)(object)hoverObject != (Object)null) ? hoverObject.GetComponentInParent<Container>() : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		if ((Object)(object)GameCamera.instance == (Object)null)
		{
			return null;
		}
		Transform transform = ((Component)GameCamera.instance).transform;
		int mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "vehicle" });
		foreach (RaycastHit item in from x in Physics.RaycastAll(transform.position, transform.forward, Reach.Value + 8f, mask)
			orderby ((RaycastHit)(ref x)).distance
			select x)
		{
			RaycastHit current = item;
			Container componentInParent = ((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Container>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				if ((Object)(object)Player.m_localPlayer != (Object)null && Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)componentInParent).transform.position) > Reach.Value)
				{
					return null;
				}
				return componentInParent;
			}
		}
		return null;
	}

	private static string Name(Container c)
	{
		return Loc(c.m_name);
	}

	internal static bool FreshLoad(Container c)
	{
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Expected O, but got Unknown
		ZNetView val = NView.Invoke(c);
		if ((Object)(object)val == (Object)null || !val.IsValid())
		{
			return false;
		}
		if (CInUse.Invoke(c))
		{
			return true;
		}
		ZDO zDO = val.GetZDO();
		Inventory val2 = CInv.Invoke(c);
		if (val2 == null)
		{
			return false;
		}
		if (CRev.Invoke(c) == zDO.DataRevision && CRev.Invoke(c) != 0)
		{
			return true;
		}
		byte[] byteArray = zDO.GetByteArray(ZDOVars.s_items, (byte[])null);
		CLoading.Invoke(c) = true;
		try
		{
			if (byteArray != null)
			{
				val2.Load(new ZPackage(byteArray));
			}
			else
			{
				val2.RemoveAll();
			}
			CRev.Invoke(c) = zDO.DataRevision;
		}
		finally
		{
			CLoading.Invoke(c) = false;
		}
		return true;
	}

	internal static string Usable(Container c)
	{
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		ZNetView val = NView.Invoke(c);
		if ((Object)(object)val == (Object)null || !val.IsValid())
		{
			return "That chest isn't loaded.";
		}
		try
		{
			if (!FreshLoad(c))
			{
				return "Couldn't read that chest's contents.";
			}
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Reading chest failed: " + ex));
			return "Couldn't read that chest's contents.";
		}
		long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
		if (CheckAccess != null && !(bool)CheckAccess.Invoke(c, new object[1] { playerID }))
		{
			return "That chest is locked to someone else.";
		}
		if (!PrivateArea.CheckAccess(((Component)c).transform.position, 0f, true, false))
		{
			return "A ward protects that chest.";
		}
		bool flag = (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible() && c.IsInUse() && val.IsOwner();
		if (c.IsInUse() && !flag)
		{
			return "Someone is using that chest.";
		}
		return null;
	}

	internal static bool InWorkbenchArea(Vector3 pos)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		return (Object)(object)CraftingStation.HaveBuildStationInRange(WorkbenchName.Value, pos) != (Object)null;
	}

	internal static string PlayerAreaRule(Player p)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if (RequireWorkbench.Value && (Object)(object)p != (Object)null && !InWorkbenchArea(((Component)p).transform.position))
		{
			return "Stand inside a " + Loc(WorkbenchName.Value) + "'s area to transfer.";
		}
		return null;
	}

	internal static bool BuiltByPlayer(Component c)
	{
		Piece val = c.GetComponent<Piece>() ?? c.GetComponentInParent<Piece>();
		if ((Object)(object)val != (Object)null)
		{
			return val.IsPlacedByPlayer();
		}
		return false;
	}

	internal static bool IsPersonal(Container c)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		return (int)c.m_privacy == 0;
	}

	internal static string TransferRule(Component c, bool asSource)
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		if (OnlyPlayerBuilt.Value && !BuiltByPlayer(c))
		{
			return "That storage wasn't built by a player.";
		}
		Container val = (Container)(object)((c is Container) ? c : null);
		if (asSource && (Object)(object)val != (Object)null && NoPersonalSources.Value && IsPersonal(val))
		{
			return "The Omni Tool doesn't take items out of personal chests.";
		}
		if (RequireWorkbench.Value && !InWorkbenchArea(c.transform.position))
		{
			return "That storage isn't inside a " + Loc(WorkbenchName.Value) + "'s area.";
		}
		return null;
	}

	internal static void PickSource()
	{
		Container val = AimedChest();
		Log.LogInfo((object)("[Transfer] right-click: aimed " + (((Object)(object)val == (Object)null) ? "nothing -> opening Advanced Transfer" : (Name(val) + " " + Describe(val)))));
		if ((Object)(object)val == (Object)null)
		{
			AdvTransfer.Show();
			return;
		}
		string text = PlayerAreaRule(Player.m_localPlayer) ?? TransferRule((Component)(object)val, asSource: true) ?? Usable(val);
		if (text != null)
		{
			Log.LogInfo((object)("[Transfer] source refused: " + text));
			Say(text);
			return;
		}
		_source = val;
		Say("Source: " + Name(val) + " (" + val.GetInventory().GetAllItems().Count + " stacks)");
	}

	internal static void Transfer()
	{
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		Container val = AimedChest();
		Log.LogInfo((object)("[Transfer] left-click: aimed " + (((Object)(object)val == (Object)null) ? "nothing" : (Name(val) + " " + Describe(val))) + ", source " + (((Object)(object)_source == (Object)null) ? "none" : (Name(_source) + " " + Describe(_source)))));
		if ((Object)(object)val == (Object)null)
		{
			if (AdvTransfer.HasActive())
			{
				Say(AdvTransfer.RunActive());
			}
			else
			{
				Say("Point at a chest, or right-click empty space to set up a preset.");
			}
			return;
		}
		if ((Object)(object)_source == (Object)null || (Object)(object)NView.Invoke(_source) == (Object)null || !NView.Invoke(_source).IsValid())
		{
			_source = null;
			Say("Right-click a chest first to pick the source.");
			return;
		}
		if ((Object)(object)val == (Object)(object)_source)
		{
			Say("That's the source chest. Point at a different one.");
			return;
		}
		string text = PlayerAreaRule(localPlayer) ?? TransferRule((Component)(object)_source, asSource: true) ?? TransferRule((Component)(object)val, asSource: false);
		if (text != null)
		{
			Log.LogInfo((object)("[Transfer] refused: " + text));
			Say(text);
			return;
		}
		if (Vector3.Distance(((Component)localPlayer).transform.position, ((Component)_source).transform.position) > SourceReach.Value)
		{
			Say("The source chest is too far away.");
			return;
		}
		string text2 = Usable(_source) ?? Usable(val);
		if (text2 != null)
		{
			Log.LogInfo((object)("[Transfer] refused: " + text2));
			Say(text2);
			return;
		}
		NView.Invoke(_source).ClaimOwnership();
		NView.Invoke(val).ClaimOwnership();
		Log.LogInfo((object)("[Transfer] after claiming: source " + Describe(_source) + ", target " + Describe(val)));
		Inventory inventory = _source.GetInventory();
		Inventory inventory2 = val.GetInventory();
		int num = Count(inventory);
		int num2 = Count(inventory2);
		bool key = ZInput.GetKey(MatchKey.Value, false);
		if (key)
		{
			foreach (ItemData item in inventory.GetAllItems().ToList())
			{
				if (inventory2.ContainsItemByName(item.m_shared.m_name))
				{
					inventory2.MoveItemToThis(inventory, item);
				}
			}
		}
		else
		{
			inventory2.MoveAll(inventory);
		}
		int num3 = num - Count(inventory);
		int num4 = Count(inventory);
		Log.LogInfo((object)("[Transfer] moved " + num3 + ", left " + num4 + (key ? " (matching only)" : "") + ". Source " + num + " -> " + Count(inventory) + ", target " + num2 + " -> " + Count(inventory2)));
		if (num + num2 != Count(inventory) + Count(inventory2))
		{
			Log.LogWarning((object)("[Transfer] COUNT MISMATCH: " + (num + num2) + " items before, " + (Count(inventory) + Count(inventory2)) + " after. Please report this log."));
			Say("Omni Tool: item count mismatch - see log");
		}
		else
		{
			Say((num3 > 0) ? ("Moved " + num3 + " items into " + Name(val) + ((num4 > 0) ? (" (" + num4 + " left - target full" + (key ? " or not matching" : "") + ")") : ".")) : (key ? "Nothing matching to move, or the target is full." : "Nothing moved - the target is full."));
		}
	}

	private static string Describe(Container c)
	{
		try
		{
			ZNetView val = NView.Invoke(c);
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return "(not loaded)";
			}
			return "(" + Count(c.GetInventory()) + " items, owner " + (val.IsOwner() ? "me" : val.GetZDO().GetOwner().ToString()) + ", inUse " + c.IsInUse() + ")";
		}
		catch (Exception ex)
		{
			return "(" + ex.GetType().Name + ")";
		}
	}

	private static int Count(Inventory inv)
	{
		int num = 0;
		foreach (ItemData allItem in inv.GetAllItems())
		{
			num += allItem.m_stack;
		}
		return num;
	}

	internal static void ClearSource()
	{
		_source = null;
		_pendingPiece = null;
	}

	private static CraftingStation Bench(Player p)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		CraftingStation obj = CraftingStation.HaveBuildStationInRange(WorkbenchName.Value, ((Component)p).transform.position);
		if ((Object)(object)obj == (Object)null)
		{
			Say("Stand within range of a " + Loc(WorkbenchName.Value) + " to use this mode.");
		}
		return obj;
	}

	private static bool InBenchArea(CraftingStation st, Vector3 pos)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		return Vector3.Distance(((Component)st).transform.position, pos) <= st.GetStationBuildRange();
	}

	private static bool HasOwnStation(Piece piece)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)piece.m_craftingStation == (Object)null)
		{
			return true;
		}
		return (Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)piece).transform.position) != (Object)null;
	}

	private static Piece AimedPiece(Player p, float maxDist)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: 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)
		if ((Object)(object)GameCamera.instance == (Object)null)
		{
			return null;
		}
		Transform transform = ((Component)GameCamera.instance).transform;
		RaycastHit val = default(RaycastHit);
		if (!Physics.Raycast(transform.position, transform.forward, ref val, maxDist, RemoveMask.Invoke(p)))
		{
			return null;
		}
		Piece val2 = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>();
		if ((Object)(object)val2 == (Object)null && (Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponent<Heightmap>() != (Object)null)
		{
			val2 = TerrainModifier.FindClosestModifierPieceInRange(((RaycastHit)(ref val)).point, 2.5f);
		}
		return val2;
	}

	internal static void RepairArea()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		CraftingStation val = Bench(localPlayer);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		foreach (WearNTear item in WearNTear.GetAllInstances().ToList())
		{
			if ((Object)(object)item == (Object)null || !InBenchArea(val, ((Component)item).transform.position) || item.GetHealthPercentage() >= 0.999f)
			{
				continue;
			}
			Piece component = ((Component)item).GetComponent<Piece>();
			if ((Object)(object)component == (Object)null)
			{
				continue;
			}
			num2++;
			if (!HasOwnStation(component) || !PrivateArea.CheckAccess(((Component)item).transform.position, 0f, false, false))
			{
				num3++;
			}
			else if (item.Repair())
			{
				num++;
				if (num4++ < 8)
				{
					component.m_placeEffect.Create(((Component)component).transform.position, ((Component)component).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
				}
			}
		}
		string text = ((num2 == 0) ? "Nothing in this workbench's area needs repair." : ("Repaired " + num + " of " + num2 + " damaged pieces."));
		if (num3 > 0)
		{
			text = text + " " + num3 + " skipped (warded, or their station isn't nearby).";
		}
		Say(text);
	}

	internal static void RepairAimed()
	{
		//IL_0055: 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_00ee: 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_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		CraftingStation val = Bench(localPlayer);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Piece val2 = AimedPiece(localPlayer, val.GetStationBuildRange() * 2f + 10f);
		if ((Object)(object)val2 == (Object)null)
		{
			Say("Point at a piece to repair it.");
			return;
		}
		if (!InBenchArea(val, ((Component)val2).transform.position))
		{
			Say("That's outside this workbench's area.");
			return;
		}
		WearNTear component = ((Component)val2).GetComponent<WearNTear>();
		if ((Object)(object)component == (Object)null)
		{
			Say("That can't be repaired.");
		}
		else if (!(CheckCanRemove != null) || (bool)CheckCanRemove.Invoke(localPlayer, new object[1] { val2 }))
		{
			if (!PrivateArea.CheckAccess(((Component)val2).transform.position, 0f, true, false))
			{
				((Character)localPlayer).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null, false);
			}
			else if (component.Repair())
			{
				val2.m_placeEffect.Create(((Component)val2).transform.position, ((Component)val2).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
				((Character)localPlayer).Message((MessageType)1, Loc(val2.m_name) + " $msg_repaired", 0, (Sprite)null, false);
			}
			else
			{
				((Character)localPlayer).Message((MessageType)1, Loc(val2.m_name) + " $msg_doesnotneedrepair", 0, (Sprite)null, false);
			}
		}
	}

	internal static void DestroyAimed()
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: 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)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		CraftingStation val = Bench(localPlayer);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Piece val2 = AimedPiece(localPlayer, val.GetStationBuildRange() * 2f + 10f);
		if ((Object)(object)val2 == (Object)null)
		{
			Say("Point at a piece to destroy it.");
		}
		else if (!InBenchArea(val, ((Component)val2).transform.position))
		{
			Say("That's outside this workbench's area.");
		}
		else if (!val2.m_canBeRemoved)
		{
			Say("That can't be removed.");
		}
		else if ((Object)(object)((Component)val2).GetComponent<Character>() != (Object)null)
		{
			Say("That can't be removed with the Omni Tool.");
		}
		else if (Location.IsInsideNoBuildLocation(((Component)val2).transform.position))
		{
			((Character)localPlayer).Message((MessageType)2, "$msg_nobuildzone", 0, (Sprite)null, false);
		}
		else if (!PrivateArea.CheckAccess(((Component)val2).transform.position, 0f, true, false))
		{
			((Character)localPlayer).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null, false);
		}
		else
		{
			if (CheckCanRemove != null && !(bool)CheckCanRemove.Invoke(localPlayer, new object[1] { val2 }))
			{
				return;
			}
			ZNetView component = ((Component)val2).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			if (!val2.CanBeRemoved())
			{
				((Character)localPlayer).Message((MessageType)2, "$msg_cantremovenow", 0, (Sprite)null, false);
				return;
			}
			if (ConfirmDestroy.Value && ((Object)(object)_pendingPiece != (Object)(object)val2 || Time.time > _pendingUntil))
			{
				_pendingPiece = val2;
				_pendingUntil = Time.time + 3f;
				Say("Click again to destroy " + Loc(val2.m_name));
				return;
			}
			_pendingPiece = null;
			IRemoved component2 = ((Component)val2).GetComponent<IRemoved>();
			if (component2 != null)
			{
				component2.OnRemoved();
			}
			WearNTear component3 = ((Component)val2).GetComponent<WearNTear>();
			Vector3 position = ((Component)val2).transform.position;
			if ((Object)(object)component3 != (Object)null)
			{
				component3.Remove(false);
			}
			else
			{
				component.ClaimOwnership();
				val2.DropResources((HitData)null);
				val2.m_placeEffect.Create(position, ((Component)val2).transform.rotation, ((Component)val2).gameObject.transform, 1f, -1, default(ZDOID));
				ZNetScene.instance.Destroy(((Component)val2).gameObject);
			}
			localPlayer.m_removeEffects.Create(position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
		}
	}

	private static void LoadRules()
	{
		Rules.Clear();
		string[] array = (RulesCfg.Value ?? "").Split(';');
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split('=');
			if (array2.Length == 2 && array2[0].Trim().Length != 0)
			{
				string[] array3 = array2[1].Split(':');
				int result = 0;
				if (array3.Length > 1)
				{
					int.TryParse(array3[1], out result);
				}
				Rules.Add(new Rule
				{
					Name = array2[0].Trim(),
					Destroy = (array3[0].Trim() == "destroy"),
					Keep = Mathf.Max(0, result)
				});
			}
		}
	}

	private static void SaveRules()
	{
		RulesCfg.Value = string.Join(";", Rules.Select((Rule r) => r.Name + "=" + (r.Destroy ? "destroy" : "drop") + ":" + r.Keep).ToArray());
	}

	internal static bool IsTool(ItemData i)
	{
		if (i != null)
		{
			if (!((Object)(object)i.m_dropPrefab != (Object)null) || !(((Object)i.m_dropPrefab).name == "BurksOmniTool"))
			{
				if (i.m_shared != null)
				{
					return i.m_shared.m_name == "Omni Tool";
				}
				return false;
			}
			return true;
		}
		return false;
	}

	internal static int ApplyRules(bool automatic)
	{
		Player p = Player.m_localPlayer;
		if ((Object)(object)p == (Object)null || ((Character)p).IsDead())
		{
			return 0;
		}
		Inventory inventory = ((Humanoid)p).GetInventory();
		int num = 0;
		foreach (Rule r in Rules)
		{
			if (automatic && !r.Destroy && !AutoDrops.Value)
			{
				continue;
			}
			List<ItemData> list = (from i in inventory.GetAllItems()
				where i.m_shared.m_name == r.Name && !i.m_equipped && !IsTool(i) && !IsFavorited(p, i)
				orderby i.m_stack
				select i).ToList();
			int num2 = list.Sum((ItemData i) => i.m_stack) - r.Keep;
			foreach (ItemData item in list)
			{
				if (num2 <= 0)
				{
					break;
				}
				int num3 = Mathf.Min(num2, item.m_stack);
				string text = Loc(item.m_shared.m_name);
				bool flag = (r.Destroy ? inventory.RemoveItem(item, num3) : ((Humanoid)p).DropItem(inventory, item, num3));
				Log.LogInfo((object)("[Assistant] " + (r.Destroy ? "destroyed " : "dropped ") + text + " x" + num3 + (automatic ? " (auto)" : "") + (flag ? "" : " - FAILED")));
				if (!flag)
				{
					break;
				}
				num2 -= num3;
				num += num3;
			}
		}
		return num;
	}

	internal static void OpenAssistant()
	{
		if (!((Object)(object)InventoryGui.instance == (Object)null))
		{
			_showPanel = true;
			if (!InventoryGui.IsVisible())
			{
				InventoryGui.instance.Show((Container)null, 1);
			}
		}
	}

	internal static void OnPickup()
	{
		if (AutoApply.Value && Rules.Count != 0)
		{
			_autoAt = Time.time + 0.4f;
		}
	}

	private void Update()
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		OmniMenu.Update();
		AdvTransfer.Update();
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		try
		{
			BuildMiddleClick(localPlayer);
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Build middle-click: " + ex.Message));
		}
		if ((int)ModeKey.Value != 0 && ZInput.GetKeyDown(ModeKey.Value, false) && Holding((Humanoid)(object)localPlayer) && !Console.IsVisible() && !Chat.instance.HasFocus())
		{
			CycleMode();
		}
		if (_autoAt > 0f && Time.time >= _autoAt)
		{
			_autoAt = -1f;
			if (((Humanoid)localPlayer).GetInventory().GetAllItems().Any(IsTool))
			{
				int num = ApplyRules(automatic: true);
				if (num > 0)
				{
					((Character)localPlayer).Message((MessageType)1, "Omni Tool cleared " + num + " items", 0, (Sprite)null, false);
				}
			}
		}
		if (_showPanel && ((Object)(object)InventoryGui.instance == (Object)null || !InventoryGui.IsVisible()))
		{
			_showPanel = false;
		}
	}

	private void OnGUI()
	{
		//IL_0076: 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_0096: Expected O, but got Unknown
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		OmniMenu.OnGUI();
		AdvTransfer.OnGUI();
		if (!Headless && _showPanel && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)InventoryGui.instance == (Object)null) && InventoryGui.IsVisible())
		{
			if (((Rect)(ref _win)).x < 0f)
			{
				((Rect)(ref _win)).x = (float)Screen.width - ((Rect)(ref _win)).width - 30f;
			}
			_win = GUILayout.Window(45525, _win, new WindowFunction(DrawPanel), "Omni Tool - Inventory Assistant", Array.Empty<GUILayoutOption>());
		}
	}

	private void DrawPanel(int id)
	{
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		bool flag = GUILayout.Toggle(AutoApply.Value, " Run automatically after pickup (tool in inventory)", Array.Empty<GUILayoutOption>());
		if (flag != AutoApply.Value)
		{
			AutoApply.Value = flag;
		}
		if (AutoApply.Value && !AutoDrops.Value)
		{
			GUILayout.Label("<size=11>Automatic runs only do Destroy rules. Drop rules run when you press Apply.</size>", Array.Empty<GUILayoutOption>());
		}
		GUILayout.Label("<b>Rules</b>  (keep this many, the rest is dropped/destroyed)", Array.Empty<GUILayoutOption>());
		_scrollRules = GUILayout.BeginScrollView(_scrollRules, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(220f) });
		Rule rule = null;
		bool flag2 = false;
		int num = ((Event.current == null || !Event.current.shift) ? 1 : 10);
		foreach (Rule rule2 in Rules)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(Loc(rule2.Name), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
			if (GUILayout.Button("-", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) }))
			{
				rule2.Keep = Mathf.Max(0, rule2.Keep - num);
				flag2 = true;
			}
			GUILayout.Label("keep " + rule2.Keep, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(62f) });
			if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) }))
			{
				rule2.Keep += num;
				flag2 = true;
			}
			if (GUILayout.Button(rule2.Destroy ? "Destroy" : "Drop", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(62f) }))
			{
				rule2.Destroy = !rule2.Destroy;
				flag2 = true;
			}
			if (GUILayout.Button("x", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) }))
			{
				rule = rule2;
			}
			GUILayout.EndHorizontal();
		}
		if (Rules.Count == 0)
		{
			GUILayout.Label("No rules yet. Add one from the list below.", Array.Empty<GUILayoutOption>());
		}
		GUILayout.EndScrollView();
		if (rule != null)
		{
			Rules.Remove(rule);
			flag2 = true;
		}
		GUILayout.Label("<b>Add a rule for</b>  (items in your inventory; hold Shift on +/- for 10)", Array.Empty<GUILayoutOption>());
		_scrollAdd = GUILayout.BeginScrollView(_scrollAdd, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(170f) });
		List<string> list = (from n in (from i in ((Humanoid)localPlayer).GetInventory().GetAllItems()
				where !IsTool(i) && !i.m_equipped
				select i.m_shared.m_name).Distinct()
			where !Rules.Any((Rule r) => r.Name == n)
			orderby Loc(n)
			select n).ToList();
		foreach (string item in list)
		{
			if (GUILayout.Button(Loc(item) + "  (" + ((Humanoid)localPlayer).GetInventory().CountItems(item, -1, true) + ")", Array.Empty<GUILayoutOption>()))
			{
				Rules.Add(new Rule
				{
					Name = item,
					Destroy = false,
					Keep = 0
				});
				flag2 = true;
			}
		}
		if (list.Count == 0)
		{
			GUILayout.Label("Nothing else to add.", Array.Empty<GUILayoutOption>());
		}
		GUILayout.EndScrollView();
		if (flag2)
		{
			SaveRules();
		}
		if (GUILayout.Button("Apply rules now", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
		{
			int num2 = ApplyRules(automatic: false);
			Say((num2 > 0) ? ("Assistant: cleared " + num2 + " items.") : "Assistant: nothing over its limit.");
		}
		GUI.DragWindow();
	}
}
[HarmonyPatch(typeof(ObjectDB), "Awake")]
public static class ObjectDB_Awake
{
	[HarmonyPriority(200)]
	public static void Postfix(ObjectDB __instance)
	{
		try
		{
			OmniToolPlugin.Register(__instance);
		}
		catch (Exception ex)
		{
			OmniToolPlugin.Log.LogError((object)ex);
		}
	}
}
[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
public static class ObjectDB_Copy
{
	[HarmonyPriority(200)]
	public static void Postfix(ObjectDB __instance)
	{
		try
		{
			OmniToolPlugin.Register(__instance);
		}
		catch (Exception ex)
		{
			OmniToolPlugin.Log.LogError((object)ex);
		}
	}
}
[HarmonyPatch(typeof(ZNetScene), "Awake")]
public static class ZNetScene_Awake
{
	public static void Postfix(ZNetScene __instance)
	{
		try
		{
			GameObject val = OmniToolPlugin.Prefab((string n) => ((IEnumerable<GameObject>)__instance.m_prefabs).FirstOrDefault((Func<GameObject, bool>)((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == n)));
			if ((Object)(object)val == (Object)null)
			{
				OmniToolPlugin.Log.LogWarning((object)"Hammer prefab not found; Omni Tool not registered.");
				return;
			}
			if (!__instance.m_prefabs.Contains(val))
			{
				__instance.m_prefabs.Add(val);
			}
			Dictionary<int, GameObject> value = Traverse.Create((object)__instance).Field("m_namedPrefabs").GetValue<Dictionary<int, GameObject>>();
			if (value != null)
			{
				value[StringExtensionMethods.GetStableHashCode(((Object)val).name)] = val;
			}
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				OmniToolPlugin.Register(ObjectDB.instance);
			}
		}
		catch (Exception ex)
		{
			OmniToolPlugin.Log.LogError((object)ex);
		}
	}
}
public class OmniModel : MonoBehaviour
{
	public Vector3 basePos;

	public Quaternion baseRot = Quaternion.identity;

	public float baseScale = 1f;

	public bool held;

	private void Awake()
	{
		Apply();
	}

	public void Apply()
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: 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_0057: 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)
		//IL_005c: 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_0069: 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_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = (held ? Model.HeldRot.Value : Model.DropRot.Value);
		float num = (held ? Model.HeldScale.Value : Model.DropScale.Value);
		Vector3 val2 = (held ? Model.HeldOffset.Value : Model.DropOffset.Value);
		((Component)this).transform.localRotation = baseRot * Quaternion.Euler(val);
		((Component)this).transform.localScale = Vector3.one * baseScale * Mathf.Max(0.01f, num);
		((Component)this).transform.localPosition = basePos + val2;
	}
}
internal static class Model
{
	internal static ConfigEntry<Vector3> HeldRot;

	internal static ConfigEntry<Vector3> HeldOffset;

	internal static ConfigEntry<Vector3> DropRot;

	internal static ConfigEntry<Vector3> DropOffset;

	internal static ConfigEntry<float> HeldScale;

	internal static ConfigEntry<float> DropScale;

	internal static ConfigEntry<bool> UseModel;

	private static Mesh _mesh;

	private static Color[] _colors;

	private static string[] _names;

	private static Bounds _bounds;

	internal static void Bind(ConfigFile c)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: 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)
		UseModel = c.Bind<bool>("Model", "UseCustomModel", true, "Show the Omni Tool's own 3D model (off = the hammer model).");
		HeldRot = c.Bind<Vector3>("Model", "HeldRotation", Vector3.zero, "Extra rotation (degrees) of the model in your hand. Tune live with the console command omnitool_pose.");
		HeldOffset = c.Bind<Vector3>("Model", "HeldOffset", Vector3.zero, "Extra offset (metres) of the model in your hand.");
		HeldScale = c.Bind<float>("Model", "HeldScale", 1f, "Size multiplier of the model in your hand.");
		DropRot = c.Bind<Vector3>("Model", "GroundRotation", Vector3.zero, "Extra rotation of the model when lying on the ground.");
		DropOffset = c.Bind<Vector3>("Model", "GroundOffset", Vector3.zero, "Extra offset of the model on the ground.");
		DropScale = c.Bind<float>("Model", "GroundScale", 1f, "Size multiplier of the model on the ground.");
	}

	private static bool Load()
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: 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_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Expected O, but got Unknown
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_mesh != (Object)null)
		{
			return true;
		}
		using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("OmniTool.model.bin"))
		{
			if (stream == null)
			{
				return false;
			}
			BinaryReader binaryReader = new BinaryReader(stream);
			int num = binaryReader.ReadInt32();
			int num2 = binaryReader.ReadInt32();
			Vector3[] array = (Vector3[])(object)new Vector3[num];
			Vector3[] array2 = (Vector3[])(object)new Vector3[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			for (int j = 0; j < num; j++)
			{
				array2[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			_mesh = new Mesh
			{
				name = "OmniToolMesh"
			};
			_mesh.vertices = array;
			_mesh.normals = array2;
			_mesh.subMeshCount = num2;
			_colors = (Color[])(object)new Color[num2];
			_names = new string[num2];
			for (int k = 0; k < num2; k++)
			{
				int count = binaryReader.ReadInt32();
				_names[k] = Encoding.UTF8.GetString(binaryReader.ReadBytes(count));
				_colors[k] = new Color(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				int num3 = binaryReader.ReadInt32();
				int[] array3 = new int[num3];
				for (int l = 0; l < num3; l++)
				{
					array3[l] = binaryReader.ReadInt32();
				}
				_mesh.SetTriangles(array3, k);
			}
			_mesh.RecalculateBounds();
			_bounds = _mesh.bounds;
		}
		return true;
	}

	private static Material[] Materials(Material basis)
	{
		//IL_002f: 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_0035: Expected O, but got Unknown
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: 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_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: 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)
		Material[] array = (Material[])(object)new Material[_colors.Length];
		for (int i = 0; i < array.Length; i++)
		{
			Material val = (((Object)(object)basis != (Object)null) ? new Material(basis) : new Material(Shader.Find("Standard")));
			((Object)val).hideFlags = (HideFlags)32;
			Color val2 = _colors[i];
			Texture2D val3 = new Texture2D(2, 2, (TextureFormat)4, false);
			((Object)val3).hideFlags = (HideFlags)32;
			val3.SetPixels((Color[])(object)new Color[4] { val2, val2, val2, val2 });
			val3.Apply();
			if (val.HasProperty("_MainTex"))
			{
				val.SetTexture("_MainTex", (Texture)(object)val3);
			}
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", Color.white);
			}
			string[] array2 = new string[6] { "_BumpMap", "_MetallicGlossMap", "_EmissionMap", "_OcclusionMap", "_DetailAlbedoMap", "_DetailNormalMap" };
			foreach (string text in array2)
			{
				if (val.HasProperty(text))
				{
					val.SetTexture(text, (Texture)null);
				}
			}
			if (val.HasProperty("_Metallic"))
			{
				val.SetFloat("_Metallic", (_names[i].Contains("Wood") || _names[i].Contains("Leather")) ? 0f : 0.5f);
			}
			if (_names[i].StartsWith("Rune") && val.HasProperty("_EmissionColor"))
			{
				val.EnableKeyword("_EMISSION");
				val.SetColor("_EmissionColor", val2 * 2.5f);
			}
			array[i] = val;
		}
		return array;
	}

	internal static void Swap(GameObject prefab)
	{
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: 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_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: 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)
		if (!UseModel.Value || !Load())
		{
			return;
		}
		Material val = null;
		Dictionary<Transform, List<Renderer>> dictionary = new Dictionary<Transform, List<Renderer>>();
		Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val2 in componentsInChildren)
		{
			if (val2 is MeshRenderer || val2 is SkinnedMeshRenderer)
			{
				if ((Object)(object)val == (Object)null && (Object)(object)val2.sharedMaterial != (Object)null)
				{
					val = val2.sharedMaterial;
				}
				Transform val3 = ((Component)val2).transform;
				while ((Object)(object)val3.parent != (Object)null && (Object)(object)val3.parent != (Object)(object)prefab.transform)
				{
					val3 = val3.parent;
				}
				if ((Object)(object)val3.parent == (Object)null)
				{
					val3 = prefab.transform;
				}
				if (!dictionary.ContainsKey(val3))
				{
					dictionary[val3] = new List<Renderer>();
				}
				dictionary[val3].Add(val2);
			}
		}
		if (dictionary.Count == 0)
		{
			OmniToolPlugin.Log.LogWarning((object)"Hammer has no visible parts; keeping its look.");
			return;
		}
		Material[] mats = Materials(val);
		foreach (KeyValuePair<Transform, List<Renderer>> item in dictionary)
		{
			Transform key = item.Key;
			Bounds target = default(Bounds);
			bool flag = true;
			foreach (Renderer item2 in item.Value)
			{
				SkinnedMeshRenderer val4 = (SkinnedMeshRenderer)(object)((item2 is SkinnedMeshRenderer) ? item2 : null);
				Bounds b;
				if ((Object)(object)val4 != (Object)null)
				{
					b = ((Renderer)val4).localBounds;
				}
				else
				{
					MeshFilter component = ((Component)item2).GetComponent<MeshFilter>();
					if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null)
					{
						continue;
					}
					b = component.sharedMesh.bounds;
				}
				Matrix4x4 val5 = key.worldToLocalMatrix * ((Component)item2).transform.localToWorldMatrix;
				foreach (Vector3 item3 in Corners(b))
				{
					Vector3 val6 = ((Matrix4x4)(ref val5)).MultiplyPoint3x4(item3);
					if (flag)
					{
						target = new Bounds(val6, Vector3.zero);
						flag = false;
					}
					else
					{
						((Bounds)(ref target)).Encapsulate(val6);
					}
				}
				item2.enabled = false;
			}
			if (!flag)
			{
				bool held = ((Object)key).name.ToLowerInvariant().Contains("attach");
				AddModel(key, target, mats, held);
			}
		}
		OmniToolPlugin.Log.LogInfo((object)("Omni Tool model fitted to " + string.Join(", ", dictionary.Keys.Select((Transform t) => ((Object)t).name).ToArray()) + "."));
	}

	private static IEnumerable<Vector3> Corners(Bounds b)
	{
		//IL_0008: 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)
		for (int i = 0; i < 8; i++)
		{
			yield return new Vector3(((i & 1) == 0) ? ((Bounds)(ref b)).min.x : ((Bounds)(ref b)).max.x, ((i & 2) == 0) ? ((Bounds)(ref b)).min.y : ((Bounds)(ref b)).max.y, ((i & 4) == 0) ? ((Bounds)(ref b)).min.z : ((Bounds)(ref b)).max.z);
		}
	}

	private static void AddModel(Transform parent, Bounds target, Material[] mats, bool held)
	{
		//IL_0011: 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_002f: 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_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: 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_0075: 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_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_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: 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_00d8: 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_00f1: 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_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: 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_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: 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_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		float[] size = new float[3]
		{
			((Bounds)(ref target)).size.x,
			((Bounds)(ref target)).size.y,
			((Bounds)(ref target)).size.z
		};
		int[] obj = new int[3] { 0, 1, 2 };
		Array.Sort(obj, (int a, int c) => size[c].CompareTo(size[a]));
		int num = obj[0];
		int num2 = obj[1];
		Vector3 zero = Vector3.zero;
		Vector3 zero2 = Vector3.zero;
		Vector3 val = ((Bounds)(ref target)).max;
		float num3 = Mathf.Abs(((Vector3)(ref val))[num]);
		val = ((Bounds)(ref target)).min;
		float num4 = ((num3 >= Mathf.Abs(((Vector3)(ref val))[num])) ? 1f : (-1f));
		((Vector3)(ref zero))[num] = num4;
		((Vector3)(ref zero2))[num2] = 1f;
		Quaternion val2 = Quaternion.LookRotation(Vector3.Cross(zero2, zero), zero);
		val = ((Bounds)(ref target)).size;
		float num5 = ((Vector3)(ref val))[num] / Mathf.Max(0.001f, ((Bounds)(ref _bounds)).size.y);
		Vector3 basePos = ((Bounds)(ref target)).center - val2 * (((Bounds)(ref _bounds)).center * num5);
		GameObject val3 = new GameObject("burks_omni_model")
		{
			layer = ((Component)parent).gameObject.layer
		};
		val3.transform.SetParent(parent, false);
		val3.AddComponent<MeshFilter>().sharedMesh = _mesh;
		((Renderer)val3.AddComponent<MeshRenderer>()).sharedMaterials = mats;
		OmniModel omniModel = val3.AddComponent<OmniModel>();
		omniModel.basePos = basePos;
		omniModel.baseRot = val2;
		omniModel.baseScale = num5;
		omniModel.held = held;
		omniModel.Apply();
	}

	internal static void ApplyAll()
	{
		OmniModel[] array = Resources.FindObjectsOfTypeAll<OmniModel>();
		foreach (OmniModel omniModel in array)
		{
			if ((Object)(object)omniModel != (Object)null)
			{
				omniModel.Apply();
			}
		}
	}

	internal static string Pose(string[] a)
	{
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: 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_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		int num = 1;
		bool flag = a.Length > 1 && a[1].ToLowerInvariant().StartsWith("g");
		if (a.Length > 1 && (flag || a[1].ToLowerInvariant().StartsWith("h")))
		{
			num = 2;
		}
		ConfigEntry<Vector3> val = (flag ? DropRot : HeldRot);
		ConfigEntry<float> val2 = (flag ? DropScale : HeldScale);
		ConfigEntry<Vector3> val3 = (flag ? DropOffset : HeldOffset);
		if (a.Length > num)
		{
			val.Value = new Vector3(f(num, val.Value.x), f(num + 1, val.Value.y), f(num + 2, val.Value.z));
			val2.Value = f(num + 3, val2.Value);
			val3.Value = new Vector3(f(num + 4, val3.Value.x), f(num + 5, val3.Value.y), f(num + 6, val3.Value.z));
			ApplyAll();
		}
		return (flag ? "Ground" : "Held") + " pose: rotation " + ((object)val.Value/*cast due to .constrained prefix*/).ToString() + ", scale " + val2.Value + ", offset " + ((object)val3.Value/*cast due to .constrained prefix*/).ToString();
		float f(int k, float d)
		{
			if (k >= a.Length || !float.TryParse(a[k], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return d;
			}
			return result;
		}
	}
}
[HarmonyPatch(typeof(Terminal), "InitTerminal")]
public static class Terminal_Init
{
	private static bool _done;

	public static void Postfix()
	{
		if (_done)
		{
			return;
		}
		try
		{
			Type nestedType = typeof(Terminal).GetNestedType("ConsoleEvent", BindingFlags.Public | BindingFlags.NonPublic);
			Type nestedType2 = typeof(Terminal).GetNestedType("ConsoleCommand", BindingFlags.Public | BindingFlags.NonPublic);
			if (nestedType == null || nestedType2 == null)
			{
				return;
			}
			Action<object> action = delegate(object args)
			{
				string text = Dispatch(Traverse.Create(args).Field("Args").GetValue<string[]>() ?? new string[0]);
				Terminal value = Traverse.Create(args).Field("Context").GetValue<Terminal>();
				if ((Object)(object)value != (Object)null)
				{
					value.AddString(text);
				}
			};
			Delegate obj = Delegate.CreateDelegate(nestedType, action.Target, action.Method, throwOnBindFailure: false);
			if ((object)obj == null)
			{
				Type parameterType = nestedType.GetMethod("Invoke").GetParameters()[0].ParameterType;
				MethodInfo method = typeof(Terminal_Init).GetMethod("Run", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(parameterType);
				obj = Delegate.CreateDelegate(nestedType, method);
			}
			string[][] array = new string[2][]
			{
				new string[2] { "omnitool_pose", "[held|ground] rx ry rz [scale] [ox oy oz] - adjust the Omni Tool model" },
				new string[2] { "omnitool_undupe", "[confirm] - remove the items duplicated by the Omni Tool 1.8.3 transfer bug" }
			};
			foreach (string[] array2 in array)
			{
				ConstructorInfo[] constructors = nestedType2.GetConstructors();
				foreach (ConstructorInfo constructorInfo in constructors)
				{
					ParameterInfo[] parameters = constructorInfo.GetParameters();
					if (parameters.Length >= 3 && !(parameters[0].ParameterType != typeof(string)) && !(parameters[1].ParameterType != typeof(string)) && !(parameters[2].ParameterType != nestedType))
					{
						object[] array3 = new object[parameters.Length];
						array3[0] = array2[0];
						array3[1] = array2[1];
						array3[2] = obj;
						for (int num3 = 3; num3 < parameters.Length; num3++)
						{
							array3[num3] = (parameters[num3].HasDefaultValue ? parameters[num3].DefaultValue : (parameters[num3].ParameterType.IsValueType ? Activator.CreateInstance(parameters[num3].ParameterType) : null));
						}
						constructorInfo.Invoke(array3);
						_done = true;
						break;
					}
				}
			}
		}
		catch (Exception ex)
		{
			OmniToolPlugin.Log.LogWarning((object)("Console command not added: " + ex.Message));
		}
	}

	private static string Dispatch(string[] a)
	{
		try
		{
			if (a.Length != 0 && a[0] == "omnitool_undupe")
			{
				return Undupe.Run(a);
			}
			return Model.Pose(a);
		}
		catch (Exception ex)
		{
			OmniToolPlugin.Log.LogWarning((object)ex);
			return "Error: " + ex.Message;
		}
	}

	private static void Run<T>(T args)
	{
		string text = Dispatch(Traverse.Create((object)args).Field("Args").GetValue<string[]>() ?? new string[0]);
		Terminal value = Traverse.Create((object)args).Field("Context").GetValue<Terminal>();
		if ((Object)(object)value != (Object)null)
		{
			value.AddString(text);
		}
	}
}
public enum Mode
{
	Transfer,
	Assistant,
	Repair,
	Destroy,
	Build
}
[HarmonyPatch(typeof(Humanoid), "StartAttack")]
public static class StartAttack_Patch
{
	[HarmonyPriority(800)]
	public static bool Prefix(Humanoid __instance, ref bool __result)
	{
		if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !OmniToolPlugin.Holding(__instance))
		{
			return true;
		}
		__result = true;
		return false;
	}
}
[HarmonyPatch(typeof(Player), "SetControls")]
public static class Controls_Patch
{
	private static bool _a;

	private static bool _s;

	private static bool _b;

	public static void Prefix(Player __instance, bool attackHold, bool secondaryAttackHold, bool blockHold)
	{
		if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
		{
			return;
		}
		bool flag = attackHold && !_a;
		bool flag2 = secondaryAttackHold && !_s;
		bool flag3 = blockHold && !_b;
		_a = attackHold;
		_s = secondaryAttackHold;
		_b = blockHold;
		if (!(flag || flag2 || flag3) || OmniUI.Busy || !OmniToolPlugin.Holding((Humanoid)(object)__instance))
		{
			return;
		}
		try
		{
			if (flag2)
			{
				OmniToolPlugin.ModeButton();
			}
			else if (flag)
			{
				OmniToolPlugin.Primary();
			}
			else
			{
				OmniToolPlugin.Secondary();
			}
		}
		catch (Exception ex)
		{
			OmniToolPlugin.Log.LogWarning((object)("Omni Tool: " + ex));
		}
	}
}
[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
public static class Unequip_Patch
{
	public static void Postfix(Humanoid __instance)
	{
		if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && !OmniToolPlugin.Holding(__instance))
		{
			OmniToolPlugin.ClearSource();
		}
	}
}
[HarmonyPatch(typeof(Player), "RemovePiece")]
public static class RemovePiece_Patch
{
	public static bool Prefix(Player __instance, ref bool __result)
	{
		if (OmniToolPlugin.BypassRemoveBlock)
		{
			return true;
		}
		if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && OmniToolPlugin.CurMode == Mode.Build && OmniToolPlugin.Holding((Humanoid)(object)__instance))
		{
			__result = false;
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(Player), "UpdatePlacement")]
public static class UpdatePlacement_Patch
{
	[HarmonyPriority(800)]
	public static void Prefix(Player __instance)
	{
		if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
		{
			return;
		}
		try
		{
			OmniToolPlugin.KeepPlaceModeInStep(__instance);
		}
		catch (Exception ex)
		{
			OmniToolPlugin.Log.LogWarning((object)("Omni Tool place mode: " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(Humanoid), "Pickup")]
public static class Pickup_Patch
{
	public static void Postfix(Humanoid __instance, bool __result)
	{
		if (__result && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
		{
			OmniToolPlugin.OnPickup();
		}
	}
}
internal static class OmniMenu
{
	internal static bool Open;

	private static float _openedAt;

	private static bool _loaded;

	private static bool _failed;

	private static Texture2D _bg;

	private static Texture2D _btn;

	private static Texture2D _btnSel;

	private static Texture2D _btnPlain;

	private static Texture2D _blade;

	private static Texture2D _chkOn;

	private static Texture2D _chkOff;

	private static readonly Texture2D[] _icons = (Texture2D[])(object)new Texture2D[5];

	private static Font _font;

	private const float ArtW = 1672f;

	private const float ArtH = 941f;

	private static float S;

	private static Vector2 O;

	private static readonly string[] Names = new string[5] { "Transfer", "Inventory Assistant", "Repair", "Destroy", "Build" };

	internal static float ClosedAt = -10f;

	private static readonly GUIStyle _st = new GUIStyle();

	private static readonly Color Gold = new Color(1f, 0.886f, 0.627f);

	private static readonly Color Title = new Color(1f, 0.84f, 0.55f);

	private static readonly Color Body = new Color(0.925f, 0.886f, 0.808f);

	private static readonly Color Hint = new Color(0.9f, 0.745f, 0.47f);

	internal static bool Busy
	{
		get
		{
			if (!Open)
			{
				return Time.unscaledTime - ClosedAt < 0.35f;
			}
			return true;
		}
	}

	internal static void Show()
	{
		if (!Load())
		{
			OmniToolPlugin.CycleMode();
			return;
		}
		Open = true;
		_openedAt = Time.unscaledTime;
	}

	internal static void Close()
	{
		if (Open)
		{
			ClosedAt = Time.unscaledTime;
		}
		Open = false;
	}

	internal static void Update()
	{
		if (Open)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || !OmniToolPlugin.Holding((Humanoid)(object)localPlayer) || InventoryGui.IsVisible() || Menu.IsVisible() || Minimap.IsOpen())
			{
				Close();
			}
		}
	}

	internal static Font GetFont()
	{
		return _font;
	}

	internal static bool EnsureLoaded()
	{
		return Load();
	}

	internal static Texture2D Tex(string name)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		//IL_005a: 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_0069: Expected O, but got Unknown
		using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("OmniTool.gui." + name + ".png");
		if (stream == null)
		{
			throw new Exception("missing resource " + name);
		}
		MemoryStream memoryStream = new MemoryStream();
		stream.CopyTo(memoryStream);
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
		{
			hideFlags = (HideFlags)32
		};
		ImageConversion.LoadImage(val, memoryStream.ToArray());
		((Texture)val).filterMode = (FilterMode)1;
		((Texture)val).wrapMode = (TextureWrapMode)1;
		return val;
	}

	private static bool Load()
	{
		if (_loaded)
		{
			return true;
		}
		if (_failed || OmniToolPlugin.Headless)
		{
			return false;
		}
		try
		{
			_bg = Tex("menu_bg");
			_btn = Tex("btn");
			_btnSel = Tex("btn_sel");
			_btnPlain = Tex("btn_plain");
			_blade = Tex("blade");
			_chkOn = Tex("chk_on");
			_chkOff = Tex("chk_off");
			_icons[0] = Tex("ico_transfer");
			_icons[1] = Tex("ico_assistant");
			_icons[2] = Tex("ico_repair");
			_icons[3] = Tex("ico_destroy");
			_icons[4] = Tex("ico_build");
			_font = FindFont();
			_loaded = true;
		}
		catch (Exception ex)
		{
			_failed = true;
			OmniToolPlugin.Log.LogWarning((object)("Omni Tool menu art failed to load, middle-click will just switch mode: " + ex.Message));
		}
		return _loaded;
	}

	private static Font FindFont()
	{
		try
		{
			Font[] source = Resources.FindObjectsOfTypeAll<Font>();
			Font val = ((IEnumerable<Font>)source).FirstOrDefault((Func<Font, bool>)((Font x) => (Object)(object)x != (Object)null && ((Object)x).name.IndexOf("Averia", StringComparison.OrdinalIgnoreCase) >= 0 && ((Object)x).name.IndexOf("Bold", StringComparison.OrdinalIgnoreCase) >= 0)) ?? ((IEnumerable<Font>)source).FirstOrDefault((Func<Font, bool>)((Font x) => (Object)(object)x != (Object)null && ((Object)x).name.IndexOf("Averia", StringComparison.OrdinalIgnoreCase) >= 0));
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return Font.CreateDynamicFontFromOSFont(new string[4] { "Georgia", "Palatino Linotype", "Book Antiqua", "Times New Roman" }, 32);
		}
		catch
		{
			return null;
		}
	}

	private static Rect R(float x, float y, float w, float h)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		return new Rect(O.x + x * S, O.y + y * S, w * S, h * S);
	}

	private static void Text(Rect r, string s, float size, Color c, TextAnchor a, bool wrap = false, bool shadow = true, FontStyle fs = (FontStyle)1)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		_st.font = _font;
		_st.fontSize = Mathf.Max(8, Mathf.RoundToInt(size * S));
		_st.alignment = a;
		_st.wordWrap = wrap;
		_st.richText = false;
		_st.fontStyle = (FontStyle)(((Object)(object)_font != (Object)null && _font.dynamic) ? ((int)fs) : 0);
		_st.clipping = (TextClipping)0;
		if (shadow)
		{
			_st.normal.textColor = new Color(0.08f, 0.03f, 0f, 0.9f);
			float num = Mathf.Max(1f, 2f * S);
			GUI.Label(new Rect(((Rect)(ref r)).x + num, ((Rect)(ref r)).y + num, ((Rect)(ref r)).width, ((Rect)(ref r)).height), s, _st);
		}
		_st.normal.textColor = c;
		GUI.Label(r, s, _st);
	}

	private static void Sprite(Texture2D t, Rect r, float cx, float cy, float cw, float ch, float alpha = 1f)
	{
		//IL_0016: 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_005e: Unknown result type (might be due to invalid IL or missing references)
		float num = ((Rect)(ref r)).width / cw;
		float num2 = ((Rect)(ref r)).height / ch;
		Color color = GUI.color;
		GUI.color = new Color(1f, 1f, 1f, alpha);
		GUI.DrawTexture(new Rect(((Rect)(ref r)).x - cx * num, ((Rect)(ref r)).y - cy * num2, (float)((Texture)t).width * num, (float)((Texture)t).height * num2), (Texture)(object)t, (ScaleMode)0, true);
		GUI.color = color;
	}

	private static bool Click(Rect r)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		Event current = Event.current;
		if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref r)).Contains(current.mousePosition))
		{
			current.Use();
			return true;
		}
		return false;
	}

	private static bool Enabled(int i)
	{
		return i switch
		{
			0 => OmniToolPlugin.EnTransfer.Value, 
			1 => OmniToolPlugin.EnAssistant.Value, 
			2 => OmniToolPlugin.EnRepair.Value, 
			4 => OmniToolPlugin.EnBuild.Value, 
			_ => OmniToolPlugin.EnDestroy.Value, 
		};
	}

	private static void Select(Mode m, bool close)
	{
		OmniToolPlugin.SetMode(m);
		if (close && OmniToolPlugin.MenuCloseOnSelect.Value)
		{
			Close();
		}
	}

	private static void Step(int dir)
	{
		Mode[] order = OmniToolPlugin.Order;
		int num = Array.IndexOf(order, OmniToolPlugin.CurMode);
		int num2 = order.Length;
		for (int i = 1; i <= num2; i++)
		{
			Mode mode = order[((num + dir * i) % num2 + num2) % num2];
			if (Enabled((int)mode))
			{
				OmniToolPlugin.SetMode(mode);
				break;
			}
		}
	}

	internal static void OnGUI()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Invalid comparison between Unknown and I4
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Invalid comparison between Unknown and I4
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: 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_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0349: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_037e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: 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_041f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0445: Unknown result type (might be due to invalid IL or missing references)
		//IL_045b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0476: Unknown result type (might be due to invalid IL or missing references)
		//IL_047b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0484: Unknown result type (might be due to invalid IL or missing references)
		if (!Open || !_loaded)
		{
			return;
		}
		Event current = Event.current;
		if ((int)current.type == 4 && (int)current.keyCode == 27)
		{
			current.Use();
			Close();
			return;
		}
		if ((int)current.type == 0 && current.button == 2 && Time.unscaledTime - _openedAt > 0.2f)
		{
			current.Use();
			Close();
			return;
		}
		float value = OmniToolPlugin.MenuScale.Value;
		S = Mathf.Min((float)Screen.width * 0.72f / 1672f, (float)Screen.height * 0.82f / 941f) * Mathf.Clamp(value, 0.3f, 2f);
		O = new Vector2(((float)Screen.width - 1672f * S) / 2f, ((float)Screen.height - 941f * S) / 2f);
		int depth = GUI.depth;
		GUI.depth = -1000;
		GUI.DrawTexture(R(0f, 0f, 1672f, 941f), (Texture)(object)_bg, (ScaleMode)0, true);
		Vector2 mousePosition = Event.current.mousePosition;
		List<int> list = OmniToolPlugin.Order.Select((Mode m) => (int)m).Where(Enabled).ToList();
		int num = Mathf.Max(1, list.Count);
		float num2 = 372f;
		float num3 = 747f;
		float num4 = 10f;
		float num5 = Mathf.Min(118f, (num3 - num2 - num4 * (float)(num - 1)) / (float)num);
		int num6 = -1;
		for (int num7 = 0; num7 < list.Count; num7++)
		{
			int num8 = list[num7];
			float num9 = num2 + (float)num7 * (num5 + num4);
			Rect r = R(490f, num9, 672f, num5);
			bool num10 = OmniToolPlugin.CurMode == (Mode)num8;
			bool flag = ((Rect)(ref r)).Contains(mousePosition);
			if (flag)
			{
				num6 = num8;
			}
			if (num10)
			{
				Sprite(_btnSel, r, 8f, 10f, 670f, 122f);
			}
			else
			{
				Sprite(_btn, r, 6f, 5f, 672f, 109f);
				if (flag)
				{
					Sprite(_btnSel, r, 8f, 10f, 670f, 122f, 0.45f);
				}
			}
			Texture2D val = _icons[num8];
			float num11 = num5 * 0.62f;
			float num12 = (float)((Texture)val).width * num11 / (float)((Texture)val).height;
			GUI.DrawTexture(R(600f - num12 / 2f, num9 + num5 / 2f - num11 / 2f, num12, num11), (Texture)(object)val, (ScaleMode)0, true);
			Text(R(715f, num9, 440f, num5), Names[num8], num5 * 0.42f, Gold, (TextAnchor)3, wrap: false, shadow: true, (FontStyle)1);
			if (Click(r))
			{
				Select((Mode)num8, close: true);
			}
		}
		GUI.DrawTexture(R(490f, 340f, ((Texture)_blade).width, ((Texture)_blade).height), (Texture)(object)_blade, (ScaleMode)0, true);
		int num13 = ((num6 >= 0) ? num6 : ((int)OmniToolPlugin.CurMode));
		Text(R(1192f, 356f, 364f, 43f), Names[num13], 30f, Title, (TextAnchor)4, wrap: false, shadow: true, (FontStyle)1);
		DrawDetails(num13, num13 == (int)OmniToolPlugin.CurMode);
		Text(R(726f, 788f, 456f, 69f), Names[(int)OmniToolPlugin.CurMode], 36f, Gold, (TextAnchor)4, wrap: false, shadow: true, (FontStyle)1);
		if (Click(R(634f, 790f, 73f, 67f)))
		{
			Step(-1);
		}
		if (Click(R(1201f, 790f, 74f, 67f)))
		{
			Step(1);
		}
		if (Click(R(1462f, 170f, 78f, 78f)))
		{
			Close();
		}
		if ((int)Event.current.type == 0)
		{
			Rect val2 = R(0f, 0f, 1672f, 941f);
			if (((Rect)(ref val2)).Contains(Event.current.mousePosition))
			{
				Event.current.Use();
			}
		}
		GUI.depth = depth;
	}

	private static void DrawDetails(int i, bool current)
	{
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: 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_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		float x = 1208f;
		float w = 340f;
		float num = 414f;
		string s;
		string s2;
		switch (i)
		{
		case 0:
			s = "Chest to chest, or saved presets that sort items into storages and smelters by name.";
			s2 = "Right-click chest: pick source\nLeft-click chest: move into it\nRight-click empty space: presets\nLeft-click empty space: run preset";
			break;
		case 1:
			s = "Keep only what you want. Extra items are dropped or destroyed by your rules.";
			s2 = "Left-click: open the rules\nRight-click: run the rules";
			break;
		case 2:
			s = "Repairs damaged pieces inside the workbench's build radius. Stand at a workbench.";
			s2 = "Left-click: repair the whole area\nRight-click: repair the aimed piece";
			break;
		case 4:
			s = "Works like the hammer: build, repair and remove pieces with the normal build menu.";
			s2 = "Right-click: build menu\nLeft-click: place\nTap middle-click: remove\nHold middle-click: this menu";
			break;
		default:
			s = "Removes a piece with a full refund, like the hammer. Only inside the workbench's radius.";
			s2 = "Left-click: destroy the aimed piece";
			break;
		}
		Text(R(x, num, w, 84f), s, 20f, Body, (TextAnchor)0, wrap: true, shadow: true, (FontStyle)0);
		num += 92f;
		Text(R(x, num, w, 90f), s2, 19f, Hint, (TextAnchor)0, wrap: true, shadow: true, (FontStyle)0);
		num += 94f;
		if (!current)
		{
			Text(R(x, 700f, w, 28f), "Click to select", 18f, Hint, (TextAnchor)4, wrap: false, shadow: true, (FontStyle)2);
			return;
		}
		switch (i)
		{
		case 1:
		{
			AutoApplyToggle(ref num, x, w);
			if (OmniToolPlugin.AutoApply.Value)
			{
				Toggle(ref num, x, w, "Auto-runs may also drop", OmniToolPlugin.AutoDrops);
			}
			else
			{
				num += 42f;
			}
			Rect r2 = R(1228f, 678f, 296f, 50f);
			Sprite(_btnPlain, r2, 6f, 5f, 672f, 109f);
			if (((Rect)(ref r2)).Contains(Event.current.mousePosition))
			{
				Sprite(_btnSel, r2, 8f, 10f, 670f, 122f, 0.45f);
			}
			Text(r2, "Edit Rules", 22f, Gold, (TextAnchor)4, wrap: false, shadow: true, (FontStyle)1);
			if (Click(r2))
			{
				Close();
				OmniToolPlugin.OpenAssistant();
			}
			break;
		}
		case 0:
		{
			Rect r = R(1228f, 678f, 296f, 50f);
			Sprite(_btnPlain, r, 6f, 5f, 672f, 109f);
			if (((Rect)(ref r)).Contains(Event.current.mousePosition))
			{
				Sprite(_btnSel, r, 8f, 10f, 670f, 122f, 0.45f);
			}
			Text(r, "Advanced Transfer", 22f, Gold, (TextAnchor)4, wrap: false, shadow: true, (FontStyle)1);
			if (Click(r))
			{
				Close();
				AdvTransfer.Show();
			}
			break;
		}
		case 3:
			Toggle(ref num, x, w, "Click twice to confirm", OmniToolPlugin.ConfirmDestroy);
			break;
		}
	}

	private static void AutoApplyToggle(ref float y, float x, float w)
	{
		Toggle(ref y, x, w, "Run after every pickup", OmniToolPlugin.AutoApply);
	}

	private static void Toggle(ref float y, float x, float w, string label, ConfigEntry<bool> e)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		Rect val = R(x, y, 34f, 31f);
		Rect r = R(x, y - 4f, w, 39f);
		GUI.DrawTexture(val, (Texture)(object)(e.Value ? _chkOn : _chkOff), (ScaleMode)0, true);
		Text(R(x + 44f, y, w - 44f, 31f), label, 20f, Body, (TextAnchor)3, wrap: false, shadow: true, (FontStyle)0);
		if (Click(r))
		{
			e.Value = !e.Value;
		}
		y += 42f;
	}
}
[HarmonyPatch(typeof(PlayerController), "TakeInput")]
public static class Menu_PC_TakeInput
{
	public static void Postfix(ref bool __result)
	{
		if (OmniUI.Blocking)
		{
			__result = false;
		}
	}
}
[HarmonyPatch(typeof(Player), "TakeInput")]
public static class Menu_Player_TakeInput
{
	public static void Postfix(ref bool __result)
	{
		if (OmniUI.Blocking)
		{
			__result = false;
		}
	}
}
[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
public static class Menu_Cursor
{
	public static void Postfix()
	{
		if (OmniUI.Blocking)
		{
			ZCursor.LockState = (CursorLockMode)0;
			ZCursor.Show();
		}
	}
}
[HarmonyPatch(typeof(Menu), "Update")]
public static class Menu_Esc
{
	public static bool Prefix()
	{
		return !OmniUI.Blocking;
	}
}
[Serializable]
public class TPreset
{
	public string Name = "New preset";

	public bool FromInventory;

	public bool SkipHotbar = true;

	public bool AllSources;

	public List<string> Sources = new List<string>();

	public string SourceFilter = "";

	public bool AllItems;

	public List<string> Categories = new List<string>();

	public List<string> Items = new List<string>();

	public List<string> Excluded = new List<string>();

	public List<string> Targets = new List<string>();

	public string TargetFilter = "";
}
[Serializable]
public class TPresetFile
{
	public List<TPreset> Presets = new List<TPreset>();

	public int Active = -1;

	public List<TGroup> Groups = new List<TGroup>();

	public int ActiveGroup = -1;
}
[Serializable]
public class TGroup
{
	public string Name = "New group";

	public List<string> Members = new List<string>();
}
internal static class AdvTransfer
{
	internal class Store
	{
		public string Id;

		public string Name;

		public string Kind;

		public string From;

		public bool Personal;

		public Container C;

		public Smelter S;

		public ZNetView NV;

		public float Dist;

		public int Stacks;
	}

	private class ItemRow
	{
		public string Name;

		public int Count;

		public ItemData Sample;
	}

	internal static bool Open;

	internal static float ClosedAt = -10f;

	private static TPresetFile _file;

	private static int _sel = -1;

	private static int _tab;

	private static string _status = "";

	internal const string NameKey = "burks_omni_name";

	private static readonly FieldRef<Smelter, ZNetView> SmeltNV = AccessTools.FieldRefAccess<Smelter, ZNetView>("m_nview");

	private static readonly MethodInfo SmAllowed = AccessTools.Method(typeof(Smelter), "IsItemAllowed", new Type[1] { typeof(string) }, (Type[])null);

	private static readonly MethodInfo SmQueue = AccessTools.Method(ty