Decompiled source of SortMyShipPleeese v1.0.0

SortMyShipPleeese.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ChatCommandAPI;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SortMyShipPleeese")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SortMyShipPleeese")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("229f8089-dd0a-4c63-8a45-fe0f7eb38c6f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LethalShipSort;

public class AutoSortToggle : ToggleCommand
{
	public override string Name => "AutoSort";

	public override string ToggleDescription => "Toggles automatic item sorting when leaving a planet";

	public override bool Value
	{
		get
		{
			return LethalShipSort.Instance.AutoSort;
		}
		set
		{
			LethalShipSort.Instance.AutoSort = value;
		}
	}
}
public struct ItemPosition
{
	public struct Flags
	{
		public const char NO_AUTO_SORT = 'A';

		public bool NoAutoSort;

		public const char KEEP_ON_CRUISER = 'C';

		public bool KeepOnCruiser;

		public const char IGNORE = 'N';

		public bool Ignore;

		public const char PARENT = 'P';

		public bool Parent;

		public const char EXACT = 'X';

		public bool Exact;

		public Flags(string s)
		{
			NoAutoSort = false;
			KeepOnCruiser = false;
			Ignore = false;
			Parent = false;
			Exact = false;
			if (string.IsNullOrEmpty(s))
			{
				return;
			}
			for (int i = 0; i < s.Length; i++)
			{
				char c = s[i];
				switch (c)
				{
				case 'A':
					NoAutoSort = true;
					break;
				case 'C':
					KeepOnCruiser = true;
					break;
				case 'N':
					Ignore = true;
					break;
				case 'P':
					Parent = true;
					break;
				case 'X':
					Exact = true;
					break;
				default:
					throw new ArgumentException("Unknown flag (" + c + ")");
				}
			}
		}

		public override string ToString()
		{
			return $"{(NoAutoSort ? 'A'.ToString() : string.Empty)}{(KeepOnCruiser ? 'C'.ToString() : string.Empty)}{(Ignore ? 'N'.ToString() : string.Empty)}{(Parent ? 'P'.ToString() : string.Empty)}{(Exact ? 'X'.ToString() : string.Empty)}";
		}

		public Flags FilterPositionRelated()
		{
			return this & new Flags
			{
				Parent = true,
				Exact = true
			};
		}

		public Flags FilterFilteringRelated()
		{
			return this & new Flags
			{
				NoAutoSort = true,
				KeepOnCruiser = true,
				Ignore = true
			};
		}

		public static Flags operator |(Flags _this, Flags other)
		{
			Flags result = default(Flags);
			result.NoAutoSort = _this.NoAutoSort || other.NoAutoSort;
			result.KeepOnCruiser = _this.KeepOnCruiser || other.KeepOnCruiser;
			result.Ignore = _this.Ignore || other.Ignore;
			result.Parent = _this.Parent || other.Parent;
			result.Exact = _this.Exact || other.Exact;
			return result;
		}

		public static Flags operator &(Flags _this, Flags other)
		{
			Flags result = default(Flags);
			result.NoAutoSort = _this.NoAutoSort && other.NoAutoSort;
			result.KeepOnCruiser = _this.KeepOnCruiser && other.KeepOnCruiser;
			result.Ignore = _this.Ignore && other.Ignore;
			result.Parent = _this.Parent && other.Parent;
			result.Exact = _this.Exact && other.Exact;
			return result;
		}
	}

	public Vector3? position;

	public Vector3? positionOffset;

	public GameObject parentTo;

	public int? floorYRot;

	public int? rotationOffset;

	public float? randomOffset;

	public Flags flags;

	public ItemPosition(string s)
	{
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
		position = null;
		positionOffset = null;
		parentTo = null;
		floorYRot = null;
		rotationOffset = null;
		randomOffset = null;
		this.flags = new Flags(string.Empty);
		Match match = new Regex("(?:([\\w/\\\\]+):)?(?:(-?\\d+(?:\\.\\d+)?)([+-]\\d+(?:\\.\\d+)?)?,)(?:(-?\\d+(?:\\.\\d+)?)([+-]\\d+(?:\\.\\d+)?)?,)(-?\\d+(?:\\.\\d+)?)([+-]\\d+(?:\\.\\d+)?)?(?:,(\\d+)([+-]\\d+)?)?(?:,(\\d+(?:\\.\\d+)?))?(?::([A-Z]+))?$", RegexOptions.Multiline).Match(s);
		if (!match.Success)
		{
			Match match2 = new Regex("([A-Z]+)$", RegexOptions.Multiline).Match(s);
			if (!match2.Success)
			{
				throw new ArgumentException("Invalid format (" + s + ")");
			}
			StringBuilder stringBuilder = new StringBuilder(">> ItemPosition init flags \"" + s + "\"");
			this.flags = new Flags(match2.Groups[1].Value);
			LethalShipSort.Logger.LogDebug((object)stringBuilder.ToString());
			return;
		}
		StringBuilder stringBuilder2 = new StringBuilder(">> ItemPosition init \"" + s + "\"");
		string value = match.Groups[2].Value;
		string value2 = match.Groups[4].Value;
		string value3 = match.Groups[6].Value;
		if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
		{
			throw new ArgumentException("Invalid x value (" + value + ")");
		}
		if (!float.TryParse(value2, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
		{
			throw new ArgumentException("Invalid y value (" + value2 + ")");
		}
		if (!float.TryParse(value3, NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
		{
			throw new ArgumentException("Invalid z value (" + value3 + ")");
		}
		position = new Vector3(result, result2, result3);
		Vector3? val = position;
		stringBuilder2.Append("\n   position is " + val.ToString());
		string value4 = match.Groups[3].Value;
		string value5 = match.Groups[5].Value;
		string value6 = match.Groups[7].Value;
		float? num = null;
		float? num2 = null;
		float? num3 = null;
		if (match.Groups[3].Success)
		{
			if (!float.TryParse(value4, NumberStyles.Float, CultureInfo.InvariantCulture, out var result4))
			{
				throw new ArgumentException("Invalid xoffset value (" + value4 + ")");
			}
			num = result4;
		}
		if (match.Groups[5].Success)
		{
			if (!float.TryParse(value5, NumberStyles.Float, CultureInfo.InvariantCulture, out var result5))
			{
				throw new ArgumentException("Invalid yoffset value (" + value5 + ")");
			}
			num2 = result5;
		}
		if (match.Groups[7].Success)
		{
			if (!float.TryParse(value6, NumberStyles.Float, CultureInfo.InvariantCulture, out var result6))
			{
				throw new ArgumentException("Invalid zoffset value (" + value6 + ")");
			}
			num3 = result6;
		}
		if (num.HasValue || num2.HasValue || num3.HasValue)
		{
			positionOffset = new Vector3(num.GetValueOrDefault(), num2.GetValueOrDefault(), num3.GetValueOrDefault());
			val = positionOffset;
			stringBuilder2.Append("\n   fixed positional offset is " + val.ToString());
		}
		else
		{
			stringBuilder2.Append("\n   fixed positional offset is not specified");
		}
		string value7 = match.Groups[8].Value;
		if (match.Groups[8].Success)
		{
			if (!int.TryParse(value7, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result7))
			{
				throw new ArgumentException("Invalid floorYRot value (" + value7 + ")");
			}
			floorYRot = result7;
			int? num4 = floorYRot;
			stringBuilder2.Append("\n   rotation is " + num4);
		}
		else
		{
			stringBuilder2.Append("\n   rotation not specified");
		}
		string value8 = match.Groups[9].Value;
		if (match.Groups[9].Success)
		{
			if (!int.TryParse(value8, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result8))
			{
				throw new ArgumentException("Invalid roffset value (" + value8 + ")");
			}
			rotationOffset = ((result8 == 0) ? null : new int?(result8));
			stringBuilder2.Append("\n   rotational offset is " + result8);
		}
		else
		{
			stringBuilder2.Append("\n   rotational offset not specified");
		}
		string value9 = match.Groups[10].Value;
		if (match.Groups[10].Success)
		{
			if (!float.TryParse(value9, NumberStyles.Float, CultureInfo.InvariantCulture, out var result9))
			{
				throw new ArgumentException("Invalid randomOffset value (" + value9 + ")");
			}
			randomOffset = result9;
			float? num5 = randomOffset;
			stringBuilder2.Append("\n   random positional offset is " + num5);
		}
		else
		{
			stringBuilder2.Append("\n   random positional offset not specified");
		}
		this.flags = new Flags(match.Groups[11].Value);
		Flags flags = this.flags;
		stringBuilder2.Append("\n   flags are " + flags.ToString());
		string value10 = match.Groups[1].Value;
		if (match.Groups[1].Success)
		{
			switch (value10.ToLower().Trim('/', '\\'))
			{
			case "cupboard":
			case "closet":
			case "storage":
			case "storagecloset":
				stringBuilder2.Append("\n   parent object is closet");
				parentTo = GameObject.Find("Environment/HangarShip/StorageCloset");
				if ((Object)(object)parentTo == (Object)null)
				{
					throw new Exception("Storage closet not found");
				}
				break;
			case "file":
			case "filecabinet":
			case "filecabinets":
				stringBuilder2.Append("\n   parent object is file cabinet");
				parentTo = GameObject.Find("Environment/HangarShip/FileCabinet");
				if ((Object)(object)parentTo == (Object)null)
				{
					throw new Exception("File cabinet not found");
				}
				break;
			case "bunkbed":
			case "bunkbeds":
				stringBuilder2.Append("\n   parent object is bunkbeds");
				parentTo = GameObject.Find("Environment/HangarShip/Bunkbeds");
				if ((Object)(object)parentTo == (Object)null)
				{
					throw new Exception("Bunkbeds not found");
				}
				break;
			case "ship":
				stringBuilder2.Append("\n   parent object is ship");
				parentTo = null;
				break;
			case "environment":
			case "none":
				stringBuilder2.Append("\n   parent object is none (environment)");
				parentTo = GameObject.Find("Environment");
				if ((Object)(object)parentTo == (Object)null)
				{
					throw new Exception("Environment not found");
				}
				break;
			default:
				stringBuilder2.Append("\n   parent object is custom (" + value10 + ") ");
				parentTo = GameObject.Find(value10);
				if ((Object)(object)parentTo == (Object)null)
				{
					throw new ArgumentException("Invalid parent object");
				}
				stringBuilder2.Append(((object)parentTo).ToString());
				break;
			}
		}
		else
		{
			stringBuilder2.Append("\n   parent object not specified");
		}
		LethalShipSort.Logger.LogDebug((object)stringBuilder2.ToString());
	}

	public override string ToString()
	{
		//IL_009a: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
		string text = "";
		if ((Object)(object)parentTo != (Object)null)
		{
			text = ((Object)parentTo).name;
			Transform parent = parentTo.transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			text += ":";
		}
		string[] obj = new string[6]
		{
			text,
			position.HasValue ? string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", position.Value.x, position.Value.y, position.Value.z) : string.Empty,
			floorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", floorYRot) : ((!randomOffset.HasValue) ? ",0" : string.Empty),
			(!rotationOffset.HasValue) ? string.Empty : string.Format(CultureInfo.InvariantCulture, "{0}{1}", (rotationOffset < 0) ? "-" : "+", Math.Abs(rotationOffset.Value)),
			(this.flags.ToString().Length > 0) ? ":" : string.Empty,
			null
		};
		Flags flags = this.flags;
		obj[5] = flags.ToString();
		return string.Concat(obj);
	}
}
[BepInPlugin("hoppinhauler.SortMyShipPleeese", "SortMyShipPleeese", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class LethalShipSort : BaseUnityPlugin
{
	[HarmonyPatch(typeof(NetworkManager), "StartClient")]
	[HarmonyPatch(typeof(NetworkManager), "StartServer")]
	[HarmonyPatch(typeof(NetworkManager), "StartHost")]
	internal class RoundOverrideResetPatch
	{
		private static void Postfix()
		{
			int count = Instance.roundOverrides.Count;
			Instance.roundOverrides.Clear();
			Logger.LogDebug((object)("roundOverrides cleared (was " + count + " items)"));
		}
	}

	[HarmonyPatch(typeof(HUDManager), "Start")]
	internal class HUDManager_Start
	{
		private static void Postfix()
		{
			if (Instance.ConfigVersion < Instance.CurrentConfigVersion)
			{
				ChatCommandAPI.PrintWarning("[SortMyShipPleeese] Your configuration file is outdated.\nPlease verify your configuration file and update it accordingly.\n<indent=10px>Expected: v" + Instance.CurrentConfigVersion + "\nConfig: v" + Instance.ConfigVersion + "</indent>");
				Logger.LogWarning((object)("Config file outdated: Expected v" + Instance.CurrentConfigVersion + ", got v" + Instance.ConfigVersion));
			}
			else if (Instance.ConfigVersion > Instance.CurrentConfigVersion)
			{
				ChatCommandAPI.PrintWarning("[SortMyShipPleeese] Your configuration file is using a newer, unsupported format.\nThere have been changes to the configuration file format which could cause errors.\nPlease verify your configuration file and mod version.\n<indent=10px>Expected: v" + Instance.CurrentConfigVersion + "\nConfig: v" + Instance.ConfigVersion + "</indent>");
				Logger.LogWarning((object)("Config file unsupported: Expected v" + Instance.CurrentConfigVersion + ", got v" + Instance.ConfigVersion));
			}
		}
	}

	private ConfigEntry<int> configVersion;

	private ConfigEntry<bool> autoSort;

	private ConfigEntry<uint> sortDelay;

	private ConfigEntry<string> defaultOneHand;

	private ConfigEntry<string> defaultTwoHand;

	private ConfigEntry<string> defaultTool;

	private ConfigEntry<string> customItemPositions;

	internal Dictionary<string, ConfigEntry<string>> itemPositions = new Dictionary<string, ConfigEntry<string>>();

	internal Dictionary<string, ConfigEntry<string>> modItemPositions = new Dictionary<string, ConfigEntry<string>>();

	internal Dictionary<string, string> vanillaItems = new Dictionary<string, string>();

	internal Dictionary<string, string> modItems = new Dictionary<string, string>();

	internal Dictionary<string, Tuple<Vector3, GameObject>> roundOverrides = new Dictionary<string, Tuple<Vector3, GameObject>>();

	private Dictionary<string, Vector3> scrapMagicScrapPositions = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase);

	private bool scrapMagicLayoutReady = false;

	private static readonly Vector3 SM_ORIGIN = new Vector3(-5.8f, 0.5f, -5f);

	private static readonly Vector3 SM_STACK = new Vector3(0f, 0.05f, 0.05f);

	public const float CUPBOARD_ABOVE = 3.2f;

	public const float CUPBOARD_TOP = 2.4f;

	public const float CUPBOARD_MIDDLE_1 = 2f;

	public const float CUPBOARD_MIDDLE_2 = 1.5f;

	public const float CUPBOARD_BOTTOM = 0.5f;

	public static LethalShipSort Instance { get; private set; }

	internal static ManualLogSource Logger { get; private set; }

	internal static Harmony Harmony { get; set; }

	public int ConfigVersion => configVersion.Value;

	public int CurrentConfigVersion => (int)((ConfigEntryBase)configVersion).DefaultValue;

	public bool AutoSort
	{
		get
		{
			return autoSort.Value;
		}
		set
		{
			autoSort.Value = value;
		}
	}

	public uint SortDelay
	{
		get
		{
			return sortDelay.Value;
		}
		set
		{
			sortDelay.Value = value;
		}
	}

	[Obsolete("Direct modifications of the modItemPositions list is not recommended, use the ItemPositionConfig functions instead")]
	public Dictionary<string, ConfigEntry<string>> modItemPositionsList => modItemPositions;

	public ItemPosition DefaultOneHand
	{
		get
		{
			try
			{
				return new ItemPosition(defaultOneHand.Value);
			}
			catch (ArgumentException)
			{
				Logger.LogError((object)("Invalid DefaultOneHand position (" + defaultOneHand.Value + "), using fallback"));
				return new ItemPosition((string)((ConfigEntryBase)defaultOneHand).DefaultValue);
			}
		}
		set
		{
			defaultOneHand.Value = value.ToString();
		}
	}

	public ItemPosition DefaultTwoHand
	{
		get
		{
			try
			{
				return new ItemPosition(defaultTwoHand.Value);
			}
			catch (ArgumentException)
			{
				Logger.LogError((object)("Invalid DefaultTwoHand position (" + defaultTwoHand.Value + "), using fallback"));
				return new ItemPosition((string)((ConfigEntryBase)defaultTwoHand).DefaultValue);
			}
		}
		set
		{
			defaultTwoHand.Value = value.ToString();
		}
	}

	public ItemPosition DefaultTool
	{
		get
		{
			try
			{
				return new ItemPosition(defaultTool.Value);
			}
			catch (ArgumentException)
			{
				Logger.LogError((object)("Invalid DefaultTool position (" + defaultTool.Value + "), using fallback"));
				return new ItemPosition((string)((ConfigEntryBase)defaultTool).DefaultValue);
			}
		}
		set
		{
			defaultTool.Value = value.ToString();
		}
	}

	public Dictionary<string, ItemPosition> CustomItemPositions
	{
		get
		{
			Dictionary<string, ItemPosition> dictionary = new Dictionary<string, ItemPosition>();
			string[] array = customItemPositions.Value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			string[] array2 = array;
			foreach (string text in array2)
			{
				string[] array3 = text.Split(new char[1] { ':' }, 2);
				if (array3.Length != 2)
				{
					Logger.LogError((object)("Invalid custom item position (" + text + ")"));
					continue;
				}
				if (dictionary.ContainsKey(array3[0]))
				{
					Logger.LogWarning((object)("Multiple CustomItemPositions for item " + array3[0]));
				}
				try
				{
					dictionary[array3[0]] = new ItemPosition(array3[1]);
				}
				catch (ArgumentException ex)
				{
					Logger.LogDebug((object)(array3[0] + " " + array3[1] + " " + ex));
					Logger.LogError((object)("Invalid custom item position (" + text + ")"));
				}
			}
			return dictionary;
		}
	}

	public Dictionary<string, ItemPosition> VanillaItemPositions
	{
		get
		{
			Dictionary<string, ItemPosition> dictionary = new Dictionary<string, ItemPosition>();
			foreach (KeyValuePair<string, ConfigEntry<string>> itemPosition in itemPositions)
			{
				try
				{
					dictionary[itemPosition.Key] = (string.IsNullOrWhiteSpace(itemPosition.Value.Value) ? default(ItemPosition) : new ItemPosition(itemPosition.Value.Value));
				}
				catch (ArgumentException)
				{
					Logger.LogError((object)("Invalid item position for " + itemPosition.Key + " (" + itemPosition.Value.Value + "), using fallback"));
					dictionary[itemPosition.Key] = (string.IsNullOrWhiteSpace((string)((ConfigEntryBase)itemPosition.Value).DefaultValue) ? default(ItemPosition) : new ItemPosition((string)((ConfigEntryBase)itemPosition.Value).DefaultValue));
				}
			}
			return dictionary;
		}
	}

	public Dictionary<string, ItemPosition> ModItemPositions
	{
		get
		{
			Dictionary<string, ItemPosition> dictionary = new Dictionary<string, ItemPosition>();
			foreach (KeyValuePair<string, ConfigEntry<string>> modItemPosition in modItemPositions)
			{
				try
				{
					dictionary[modItemPosition.Key] = (string.IsNullOrWhiteSpace(modItemPosition.Value.Value) ? default(ItemPosition) : new ItemPosition(modItemPosition.Value.Value));
				}
				catch (ArgumentException)
				{
					Logger.LogError((object)("Invalid mod item position for " + modItemPosition.Key + " (" + modItemPosition.Value.Value + "), using fallback"));
					dictionary[modItemPosition.Key] = (string.IsNullOrWhiteSpace((string)((ConfigEntryBase)modItemPosition.Value).DefaultValue) ? default(ItemPosition) : new ItemPosition((string)((ConfigEntryBase)modItemPosition.Value).DefaultValue));
				}
			}
			return dictionary;
		}
	}

	private static string ScrapMagicKeyFromItemName(string itemName)
	{
		if (itemName == null)
		{
			return "";
		}
		return itemName.ToLowerInvariant().Replace(" ", "_").Replace("-", "_");
	}

	private void EnsureScrapMagicLayout()
	{
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: 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_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: 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_0236: 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_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: 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)
		if (scrapMagicLayoutReady)
		{
			return;
		}
		StartOfRound instance = StartOfRound.Instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)instance.allItemsList == (Object)null || instance.allItemsList.itemsList == null)
		{
			return;
		}
		try
		{
			List<Item> source = instance.allItemsList.itemsList.Where((Item i) => (Object)(object)i != (Object)null && i.isScrap).ToList();
			List<Item> source2 = (from g in source.GroupBy<Item, string>((Item i) => ScrapMagicKeyFromItemName(i.itemName), StringComparer.Ordinal)
				select g.First()).OrderBy<Item, string>((Item i) => ScrapMagicKeyFromItemName(i.itemName), StringComparer.Ordinal).ThenBy((Item i) => (float)(i.minValue + i.maxValue) * 0.5f).ToList();
			List<Item> list = source2.Where((Item i) => i.twoHanded).ToList();
			List<Item> list2 = source2.Where((Item i) => !i.twoHanded).ToList();
			Dictionary<string, Vector3> dictionary = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase);
			for (int j = 0; j < list.Count; j++)
			{
				string key = ScrapMagicKeyFromItemName(list[j].itemName);
				Vector3 value = SM_ORIGIN + new Vector3((float)j * 0.7f, 3f, 0f);
				dictionary[key] = value;
			}
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.6f, 0.7f);
			for (int k = 0; k < list2.Count; k++)
			{
				int num = k / 4;
				int num2 = k % 4;
				float num3 = ((num % 2 == 0) ? 0f : 0.5f);
				float num4 = (float)num * val.x;
				float num5 = ((float)num2 + num3) * val.y;
				string key2 = ScrapMagicKeyFromItemName(list2[k].itemName);
				Vector3 value2 = SM_ORIGIN + new Vector3(num4, num5, 0f);
				dictionary[key2] = value2;
			}
			scrapMagicScrapPositions = dictionary;
			scrapMagicLayoutReady = true;
			Logger.LogDebug((object)("ScrapMagic layout cache created: " + scrapMagicScrapPositions.Count + " scrap types"));
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Failed to build ScrapMagic layout: " + ex));
		}
	}

	public ItemPosition GetPosition(GrabbableObject item)
	{
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04be: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
		string text = Utils.ItemKey(item);
		ItemPosition? itemPosition = null;
		Logger.LogDebug((object)(">> GetPosition(" + ((object)item)?.ToString() + ") itemName:" + text + " isScrap:" + item.itemProperties.isScrap + " twoHanded:" + item.itemProperties.twoHanded));
		ConfigEntry<string> value2;
		ItemPosition value3;
		if (roundOverrides.TryGetValue(text.ToLowerInvariant(), out var value))
		{
			itemPosition = new ItemPosition
			{
				position = value.Item1,
				parentTo = value.Item2
			};
			ManualLogSource logger = Logger;
			ItemPosition? itemPosition2 = itemPosition;
			logger.LogDebug((object)("<< GetPosition (roundOverrides) " + itemPosition2.ToString()));
		}
		else if (itemPositions.TryGetValue(text, out value2))
		{
			try
			{
				if (!string.IsNullOrWhiteSpace(value2.Value))
				{
					itemPosition = new ItemPosition(value2.Value);
					ManualLogSource logger2 = Logger;
					string[] obj = new string[5] { "<< GetPosition (itemPositions) ", null, null, null, null };
					ItemPosition? itemPosition2 = itemPosition;
					obj[1] = itemPosition2.ToString();
					obj[2] = " (";
					obj[3] = value2.Value;
					obj[4] = ")";
					logger2.LogDebug((object)string.Concat(obj));
				}
			}
			catch (ArgumentException)
			{
				Logger.LogError((object)("Invalid item position for " + text + " (" + value2.Value + "), using fallback"));
				if (!string.IsNullOrWhiteSpace((string)((ConfigEntryBase)value2).DefaultValue))
				{
					itemPosition = new ItemPosition((string)((ConfigEntryBase)value2).DefaultValue);
					ManualLogSource logger3 = Logger;
					string[] obj2 = new string[5] { "<< GetPosition (itemPositions DefaultValue) ", null, null, null, null };
					ItemPosition? itemPosition2 = itemPosition;
					obj2[1] = itemPosition2.ToString();
					obj2[2] = " (";
					obj2[3] = ((ConfigEntryBase)value2).DefaultValue?.ToString();
					obj2[4] = ")";
					logger3.LogDebug((object)string.Concat(obj2));
				}
			}
		}
		else if (modItemPositions.TryGetValue(text, out value2))
		{
			try
			{
				if (!string.IsNullOrWhiteSpace(value2.Value))
				{
					itemPosition = new ItemPosition(value2.Value);
					ManualLogSource logger4 = Logger;
					string[] obj3 = new string[5] { "<< GetPosition (modItemPositions) ", null, null, null, null };
					ItemPosition? itemPosition2 = itemPosition;
					obj3[1] = itemPosition2.ToString();
					obj3[2] = " (";
					obj3[3] = value2.Value;
					obj3[4] = ")";
					logger4.LogDebug((object)string.Concat(obj3));
				}
			}
			catch (ArgumentException)
			{
				Logger.LogError((object)("Invalid mod item position for " + text + " (" + value2.Value + "), using fallback"));
				try
				{
					if (!string.IsNullOrWhiteSpace((string)((ConfigEntryBase)value2).DefaultValue))
					{
						itemPosition = new ItemPosition((string)((ConfigEntryBase)value2).DefaultValue);
						ManualLogSource logger5 = Logger;
						string[] obj4 = new string[5] { "<< GetPosition (modItemPositions DefaultValue) ", null, null, null, null };
						ItemPosition? itemPosition2 = itemPosition;
						obj4[1] = itemPosition2.ToString();
						obj4[2] = " (";
						obj4[3] = ((ConfigEntryBase)value2).DefaultValue?.ToString();
						obj4[4] = ")";
						logger5.LogDebug((object)string.Concat(obj4));
					}
				}
				catch (ArgumentException ex2)
				{
					Logger.LogError((object)("Invalid default mod item position for " + text + " (" + value2.Value + "). The mod developer seems to have screwed something up"));
					Logger.LogError((object)ex2);
				}
			}
		}
		else if (CustomItemPositions.TryGetValue(text, out value3))
		{
			itemPosition = value3;
			ManualLogSource logger6 = Logger;
			ItemPosition? itemPosition2 = itemPosition;
			logger6.LogDebug((object)("<< GetPosition (CustomItemPositions) " + itemPosition2.ToString()));
		}
		if (!itemPosition.HasValue && item.itemProperties.isScrap)
		{
			EnsureScrapMagicLayout();
			string key = ScrapMagicKeyFromItemName(item.itemProperties.itemName);
			if (scrapMagicLayoutReady && scrapMagicScrapPositions.TryGetValue(key, out var value4))
			{
				itemPosition = new ItemPosition
				{
					position = value4,
					positionOffset = SM_STACK,
					parentTo = null,
					floorYRot = -1,
					rotationOffset = null,
					randomOffset = null,
					flags = new ItemPosition.Flags('X'.ToString())
				};
				ManualLogSource logger7 = Logger;
				ItemPosition? itemPosition2 = itemPosition;
				logger7.LogDebug((object)("<< GetPosition (ScrapMagic layout) " + itemPosition2.ToString()));
			}
		}
		if (!itemPosition.HasValue)
		{
			itemPosition = ((!item.itemProperties.isScrap) ? DefaultTool : (item.itemProperties.twoHanded ? DefaultTwoHand : DefaultOneHand));
			ManualLogSource logger8 = Logger;
			ItemPosition? itemPosition2 = itemPosition;
			logger8.LogDebug((object)("<< GetPosition (Default*) " + itemPosition2.ToString()));
		}
		else if (!itemPosition.Value.position.HasValue)
		{
			ItemPosition itemPosition3 = ((!item.itemProperties.isScrap) ? DefaultTool : (item.itemProperties.twoHanded ? DefaultTwoHand : DefaultOneHand));
			itemPosition = new ItemPosition
			{
				flags = (itemPosition.Value.flags.FilterFilteringRelated() | itemPosition3.flags.FilterPositionRelated()),
				position = itemPosition3.position,
				parentTo = itemPosition3.parentTo
			};
			ManualLogSource logger9 = Logger;
			ItemPosition? itemPosition2 = itemPosition;
			logger9.LogDebug((object)("<< GetPosition (Default* with flags) " + itemPosition2.ToString()));
		}
		return itemPosition.Value;
	}

	private void Awake()
	{
		Logger = ((BaseUnityPlugin)this).Logger;
		Instance = this;
		configVersion = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ConfigVersion", 5, "The version of this config file");
		autoSort = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoSort", false, "Whether to automatically sort the ship when leaving a planet (toggle ingame with /autosort)");
		sortDelay = ((BaseUnityPlugin)this).Config.Bind<uint>("General", "SortDelay", 0u, "The amount of milliseconds to wait between moving items, mostly for the satisfying visual effect.\nYou can't pick anything up while sorting items.");
		BindItemPositionConfigs();
		Patch();
		new SortItemsCommand();
		new AutoSortToggle();
		new SetItemPositionCommand();
		new PrintItemNames();
		Logger.LogInfo((object)"hoppinhauler.SortMyShipPleeese v1.0.0 has loaded!");
	}

	private void Patch()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		if (Harmony == null)
		{
			Harmony = new Harmony("hoppinhauler.SortMyShipPleeese");
		}
		Logger.LogDebug((object)"Patching...");
		Harmony.PatchAll();
		Logger.LogDebug((object)"Finished patching!");
	}

	private void BindItemPositionConfigs()
	{
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0317: Unknown result type (might be due to invalid IL or missing references)
		//IL_0477: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_053e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0625: Unknown result type (might be due to invalid IL or missing references)
		//IL_065b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0680: Unknown result type (might be due to invalid IL or missing references)
		//IL_06be: Unknown result type (might be due to invalid IL or missing references)
		//IL_06fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_073a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0778: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_082d: Unknown result type (might be due to invalid IL or missing references)
		//IL_086b: Unknown result type (might be due to invalid IL or missing references)
		//IL_08a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_090b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0949: Unknown result type (might be due to invalid IL or missing references)
		//IL_0987: Unknown result type (might be due to invalid IL or missing references)
		//IL_09c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_09fe: Unknown result type (might be due to invalid IL or missing references)
		defaultOneHand = ((BaseUnityPlugin)this).Config.Bind<string>("Items", "DefaultOneHand", "-2.25,3,-5.25,0.05", "Default position for one-handed items.");
		defaultTwoHand = ((BaseUnityPlugin)this).Config.Bind<string>("Items", "DefaultTwoHand", "-4.5,3,-5.25,0.05", "Default position for two-handed items.");
		defaultTool = ((BaseUnityPlugin)this).Config.Bind<string>("Items", "DefaultTool", string.Format(CultureInfo.InvariantCulture, "cupboard:-2,0.6,{0},0,0.02:{1}{2}", 0.5f, 'C', 'P'), "Default position for tool items.");
		VItemPositionConfig("Airhorn");
		VItemPositionConfig("LungApparatus", "Apparatice", new Vector3(-6.8f, 4.4f, -6.65f));
		itemPositions["LungApparatusTurnedOff"] = itemPositions["LungApparatus"];
		VItemPositionConfig("HandBell", "Brass bell");
		VItemPositionConfig("BigBolt", "Big bolt");
		VItemPositionConfig("Bone");
		VItemPositionConfig("BinFullOfBottles", "Bottles");
		VItemPositionConfig("Hairbrush", "Hair brush");
		VItemPositionConfig("Candy");
		VItemPositionConfig("CashRegisterItem", "Cash register");
		VItemPositionConfig("ChemicalJug", "Chemical jug");
		VItemPositionConfig("Clock");
		VItemPositionConfig("Clownhorn", "Clown horn");
		VItemPositionConfig("ComedyMask", "Comedy");
		VItemPositionConfig("ControlPad", "Control pad");
		VItemPositionConfig("CookieMoldPan", "Cookie mold pan");
		VItemPositionConfig("Dustpan", "Dust pan");
		VItemPositionConfig("Ear");
		VItemPositionConfig("EasterEgg", "Easter egg");
		VItemPositionConfig("KiwiBabyItem", "Egg", new Vector3(4.85f, 2f, -4f));
		VItemPositionConfig("EggBeater", "Egg beater");
		VItemPositionConfig("FancyLamp", "Fancy lamp");
		VItemPositionConfig("Flask");
		VItemPositionConfig("SeveredFootLOD0", "Foot");
		VItemPositionConfig("GarbageLid", "Garbage lid");
		VItemPositionConfig("GiftBox", "Gift box");
		VItemPositionConfig("GoldBar", "Gold Bar");
		VItemPositionConfig("FancyGlass", "Golden cup");
		VItemPositionConfig("SeveredHandLOD0", "Hand");
		VItemPositionConfig("HeartContainer", "Heart");
		VItemPositionConfig("Hairdryer");
		VItemPositionConfig("RedLocustHive", "Bee hive", new Vector3(-6.8f, 4.4f, -5.65f));
		VItemPositionConfig("DiyFlashbang", "Homemade Flashbang");
		VItemPositionConfig("PickleJar", "Jar of pickles");
		VItemPositionConfig("KnifeItem", "Kitchen knife", new Vector3(-1.9f, 0.6f, 1.5f), isTool: false, true, true, 0);
		VItemPositionConfig("SeveredThighLOD0", "Knee");
		VItemPositionConfig("Cog", "Large axle");
		VItemPositionConfig("LaserPointer", "Laser pointer");
		VItemPositionConfig("Magic7Ball", "Magic 7 ball");
		VItemPositionConfig("MagnifyingGlass", "Magnifying glass");
		VItemPositionConfig("MetalSheet", "Tattered metal sheet");
		VItemPositionConfig("Mug", "Coffee mug");
		VItemPositionConfig("OldPhone", "Old phone");
		VItemPositionConfig("Painting");
		VItemPositionConfig("PerfumeBottle", "Perfume bottle");
		VItemPositionConfig("PillBottle", "Pill bottle");
		VItemPositionConfig("PlasticCup", "Plastic cup");
		VItemPositionConfig("FishTestProp", "Plastic fish");
		VItemPositionConfig("RedSodaCan", "Red soda");
		VItemPositionConfig("Remote");
		VItemPositionConfig("RibcageBone", "Ribcage");
		VItemPositionConfig("FancyRing", "Wedding ring");
		VItemPositionConfig("RubberDucky", "Rubber ducky");
		VItemPositionConfig("ShotgunItem", "Double-barrel", new Vector3(8.75f, 2f, -5.5f), isTool: false, null, true, 0);
		ItemPositionConfig(((BaseUnityPlugin)this).Config, "ShotgunItem-1", "Double-barrel (1 bullet)", new Vector3(8.6f, 2f, -5.5f), isTool: false, null, true, 0, "ShotgunExtensions");
		ItemPositionConfig(((BaseUnityPlugin)this).Config, "ShotgunItem-2", "Double-barrel (2 bullets)", new Vector3(8.45f, 2f, -5.5f), isTool: false, null, true, 0, "ShotgunExtensions");
		VItemPositionConfig("SoccerBall", "Soccer ball", new Vector3(-6.8f, 4.4f, -7.75f));
		VItemPositionConfig("SteeringWheel", "Steering wheel");
		VItemPositionConfig("StopSign", "Stop sign");
		VItemPositionConfig("TeaKettle", "Tea Kettle");
		VItemPositionConfig("Dentures", "Teeth");
		VItemPositionConfig("ToiletPaperRolls", "Toilet paper");
		VItemPositionConfig("Toothpaste");
		VItemPositionConfig("Tongue");
		VItemPositionConfig("ToyCube", "Toy cube");
		VItemPositionConfig("RobotToy", "Robot Toy");
		VItemPositionConfig("ToyTrain", "Toy train");
		VItemPositionConfig("TragedyMask", "Tragedy");
		VItemPositionConfig("EnginePart", "V-type engine");
		VItemPositionConfig("WhoopieCushion", "Whoopie cushion", new Vector3(9f, 2f, -8.25f));
		VItemPositionConfig("YieldSign", "Yield sign");
		VItemPositionConfig("ZeddogPlushie", "Zed Dog", new Vector3(9f, 1.21f, -5.55f));
		VItemPositionConfig("WalkieTalkie", "Walkie-talkie", new Vector3(-1.4f, 0.6f, 2.4f), isTool: true, null, null, 0);
		VItemPositionConfig("BBFlashlight", "Flashlight", new Vector3(-1.3f, 0.2f, 2f), isTool: true, null, null, 0);
		VItemPositionConfig("ShovelItem", "Shovel", new Vector3(-1.5f, 0.3f, 1.5f), isTool: true, null, null, 0);
		VItemPositionConfig("LockPickerItem", "Lockpicker", new Vector3(-2f, 0.5f, 2.4f), isTool: true, null, null, 0);
		VItemPositionConfig("FlashlightItem", "Pro-flashlight", new Vector3(-1.3f, 0.65f, 2f), isTool: true, null, null, 0);
		VItemPositionConfig("StunGrenade", "Stun grenade", new Vector3(-1.2f, 0.5f, 2f), isTool: true, null, null, 0);
		VItemPositionConfig("Boombox", new Vector3(-0.3f, 0.5f, 3.2f), isTool: true, null, null, 0);
		VItemPositionConfig("TZPChemical", "TZP-Inhalant", new Vector3(-0.55f, 0.2f, 2f), isTool: true, null, null, 0);
		VItemPositionConfig("PatcherGunItem", "Zap gun", new Vector3(-1.1f, 0.6f, 2.4f), isTool: true, null, null, 0);
		VItemPositionConfig("JetpackItem", "Jetpack", new Vector3(-0.3f, 0.2f, 0.5f), isTool: true, null, null, 0);
		VItemPositionConfig("ExtensionLadderItem", "Extension ladder", v: true);
		VItemPositionConfig("RadarBoosterDevice", "Radar booster", v: true);
		VItemPositionConfig("SprayPaintItem", "Spray paint", new Vector3(-1.7f, 0.5f, 2f), isTool: true, null, null, 0);
		VItemPositionConfig("WeedKillerItem", "Weed killer", new Vector3(-2.05f, 0.5f, 2f), isTool: true, null, null, 0);
		VItemPositionConfig("BeltBagItem", "Belt bag", new Vector3(-0.35f, 0.5f, 2.3000002f), isTool: true, null, null, 0);
		VItemPositionConfig("Key", new Vector3(-0.3f, 0.6f, 1.5f), isTool: true, null, null, 0);
		VItemPositionConfig("ShotgunShell", "Shotgun Shell", new Vector3(-0.3f, 0.6f, 2f), isTool: true, null, null, 0);
		customItemPositions = ((BaseUnityPlugin)this).Config.Bind<string>("Items", "CustomItemPositions", "MyItem1:0,0,0;MyItem2:cupboard:1.5,-2,3", "Semicolon-separated list of internal item names and their positions.");
	}

	private void VItemPositionConfig(string internalName, string itemName)
	{
		VItemPositionConfig(internalName, itemName, isTool: false, null);
	}

	private void VItemPositionConfig(string internalName, string itemName, bool isTool, bool? defaultKeepOnCruiser)
	{
		itemPositions[internalName] = ((BaseUnityPlugin)this).Config.Bind<string>(isTool ? "Tools" : "Scrap", internalName, string.Format(CultureInfo.InvariantCulture, "{0}", defaultKeepOnCruiser.GetValueOrDefault(isTool) ? 'C'.ToString() : string.Empty), "Position for the " + itemName + " item.");
		vanillaItems[itemName.ToLowerInvariant()] = internalName.ToLowerInvariant();
	}

	private void VItemPositionConfig(string internalName, string itemName, bool v)
	{
		VItemPositionConfig(internalName, itemName, isTool: false, null);
	}

	private void VItemPositionConfig(string itemName, bool isTool, bool? defaultKeepOnCruiser)
	{
		itemPositions[itemName] = ((BaseUnityPlugin)this).Config.Bind<string>(isTool ? "Tools" : "Scrap", itemName, string.Format(CultureInfo.InvariantCulture, "{0}", defaultKeepOnCruiser.GetValueOrDefault(isTool) ? 'C'.ToString() : string.Empty), "Position for the " + itemName + " item.");
		vanillaItems[itemName.ToLowerInvariant()] = itemName.ToLowerInvariant();
	}

	private void VItemPositionConfig(string itemName)
	{
		VItemPositionConfig(itemName, isTool: false, null);
	}

	public void ItemPositionConfig(ConfigFile configFile, string internalName, string itemName, bool isTool, bool? defaultKeepOnCruiser, string section)
	{
		if (modItemPositions.ContainsKey(internalName))
		{
			Logger.LogWarning((object)("Multiple configuration values registered for mod item position " + internalName));
		}
		modItemPositions[internalName] = configFile.Bind<string>((!string.IsNullOrEmpty(section)) ? section : (isTool ? "Tools" : "Scrap"), internalName, string.Format(CultureInfo.InvariantCulture, "{0}", defaultKeepOnCruiser.GetValueOrDefault(isTool) ? 'C'.ToString() : string.Empty), "Position for the " + itemName + " item.");
		modItems[itemName.ToLowerInvariant()] = internalName.ToLowerInvariant();
	}

	public void ItemPositionConfig(ConfigFile configFile, string internalName, string itemName, bool isTool)
	{
		ItemPositionConfig(configFile, internalName, itemName, isTool, null, null);
	}

	public void ItemPositionConfig(ConfigFile configFile, string itemName, bool isTool, bool? defaultKeepOnCruiser, string section)
	{
		if (modItemPositions.ContainsKey(itemName))
		{
			Logger.LogWarning((object)("Multiple configuration values registered for mod item position " + itemName));
		}
		modItemPositions[itemName] = configFile.Bind<string>((!string.IsNullOrEmpty(section)) ? section : (isTool ? "Tools" : "Scrap"), itemName, string.Format(CultureInfo.InvariantCulture, "{0}", defaultKeepOnCruiser.GetValueOrDefault(isTool) ? 'C'.ToString() : string.Empty), "Position for the " + itemName + " item.");
		modItems[itemName.ToLowerInvariant()] = itemName.ToLowerInvariant();
	}

	public void ItemPositionConfig(ConfigFile configFile, string itemName, bool isTool)
	{
		ItemPositionConfig(configFile, itemName, isTool, null, null);
	}

	private static string Flags(bool keepOnCruiser, bool inCupboard)
	{
		if (!keepOnCruiser && !inCupboard)
		{
			return string.Empty;
		}
		return ":" + (keepOnCruiser ? 'C'.ToString() : string.Empty) + (inCupboard ? 'P'.ToString() : string.Empty);
	}

	private void VItemPositionConfig(string internalName, string itemName, Vector3 defaultPosition, bool isTool, bool? defaultInCupboard, bool? defaultKeepOnCruiser, int? defaultFloorYRot)
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		bool valueOrDefault = defaultInCupboard.GetValueOrDefault(isTool);
		bool valueOrDefault2 = defaultKeepOnCruiser.GetValueOrDefault(isTool);
		itemPositions[internalName] = ((BaseUnityPlugin)this).Config.Bind<string>(isTool ? "Tools" : "Scrap", internalName, string.Format(CultureInfo.InvariantCulture, "{0}{1},{2},{3}{4}{5}", valueOrDefault ? "cupboard:" : "", defaultPosition.x, defaultPosition.y, defaultPosition.z, defaultFloorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", defaultFloorYRot) : string.Empty, Flags(valueOrDefault2, valueOrDefault)), "Position for the " + itemName + " item.");
		vanillaItems[itemName.ToLowerInvariant()] = internalName.ToLowerInvariant();
	}

	private void VItemPositionConfig(string internalName, string itemName, Vector3 defaultPosition)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		VItemPositionConfig(internalName, itemName, defaultPosition, isTool: false, null, null, null);
	}

	private void VItemPositionConfig(string itemName, Vector3 defaultPosition, bool isTool, bool? defaultInCupboard, bool? defaultKeepOnCruiser, int? defaultFloorYRot)
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		bool valueOrDefault = defaultInCupboard.GetValueOrDefault(isTool);
		bool valueOrDefault2 = defaultKeepOnCruiser.GetValueOrDefault(isTool);
		itemPositions[itemName] = ((BaseUnityPlugin)this).Config.Bind<string>(isTool ? "Tools" : "Scrap", itemName, string.Format(CultureInfo.InvariantCulture, "{0}{1},{2},{3}{4}{5}", valueOrDefault ? "cupboard:" : "", defaultPosition.x, defaultPosition.y, defaultPosition.z, defaultFloorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", defaultFloorYRot) : string.Empty, Flags(valueOrDefault2, valueOrDefault)), "Position for the " + itemName + " item.");
		vanillaItems[itemName.ToLowerInvariant()] = itemName.ToLowerInvariant();
	}

	private void VItemPositionConfig(string itemName, Vector3 defaultPosition, bool isTool, int? defaultFloorYRot)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		VItemPositionConfig(itemName, defaultPosition, isTool, null, null, defaultFloorYRot);
	}

	private void VItemPositionConfig(string itemName, Vector3 defaultPosition, bool isTool)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		VItemPositionConfig(itemName, defaultPosition, isTool, null, null, null);
	}

	public void ItemPositionConfig(ConfigFile configFile, string internalName, string itemName, Vector3 defaultPosition, bool isTool, bool? defaultInCupboard, bool? defaultKeepOnCruiser, int? defaultFloorYRot, string section)
	{
		//IL_0085: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
		if (modItemPositions.ContainsKey(internalName))
		{
			Logger.LogWarning((object)("Multiple configuration values registered for mod item position " + internalName));
		}
		bool valueOrDefault = defaultInCupboard.GetValueOrDefault(isTool);
		bool valueOrDefault2 = defaultKeepOnCruiser.GetValueOrDefault(isTool);
		modItemPositions[internalName] = configFile.Bind<string>((!string.IsNullOrEmpty(section)) ? section : (isTool ? "Tools" : "Scrap"), internalName, string.Format(CultureInfo.InvariantCulture, "{0}{1},{2},{3}{4}{5}", valueOrDefault ? "cupboard:" : "", defaultPosition.x, defaultPosition.y, defaultPosition.z, defaultFloorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", defaultFloorYRot) : string.Empty, Flags(valueOrDefault2, valueOrDefault)), "Position for the " + itemName + " item.");
		modItems[itemName.ToLowerInvariant()] = internalName.ToLowerInvariant();
	}

	public void ItemPositionConfig(ConfigFile configFile, string itemName, Vector3 defaultPosition, bool isTool, bool? defaultInCupboard, bool? defaultKeepOnCruiser, int? defaultFloorYRot, string section)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		if (modItemPositions.ContainsKey(itemName))
		{
			Logger.LogWarning((object)("Multiple configuration values registered for mod item position " + itemName));
		}
		bool valueOrDefault = defaultInCupboard.GetValueOrDefault(isTool);
		bool valueOrDefault2 = defaultKeepOnCruiser.GetValueOrDefault(isTool);
		modItemPositions[itemName] = configFile.Bind<string>((!string.IsNullOrEmpty(section)) ? section : (isTool ? "Tools" : "Scrap"), itemName, string.Format(CultureInfo.InvariantCulture, "{0}{1},{2},{3}{4}{5}", valueOrDefault ? "cupboard:" : "", defaultPosition.x, defaultPosition.y, defaultPosition.z, defaultFloorYRot.HasValue ? string.Format(CultureInfo.InvariantCulture, ",{0}", defaultFloorYRot) : string.Empty, Flags(valueOrDefault2, valueOrDefault)), "Position for the " + itemName + " item.");
		modItems[itemName.ToLowerInvariant()] = itemName.ToLowerInvariant();
	}
}
internal static class MyPluginInfo
{
	public const string PLUGIN_GUID = "hoppinhauler.SortMyShipPleeese";

	public const string PLUGIN_NAME = "SortMyShipPleeese";

	public const string PLUGIN_VERSION = "1.0.0";
}
public class PrintItemNames : Command
{
	public override string Name => "PrintItemNames";

	public override string[] Commands => new string[2]
	{
		"itemnames",
		((Command)this).Name
	};

	public override string Description => "Lists all currently loaded item names which do not have assigned sorting positions";

	public override string[] Syntax => new string[2] { "", "[ -a | --all ]" };

	public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
	{
		error = "The ship must be in orbit";
		if (!StartOfRound.Instance.inShipPhase)
		{
			return false;
		}
		bool flag = args.Contains("-a") || args.Contains("--all");
		error = "No items on the ship";
		Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
		GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
		foreach (GrabbableObject val in array)
		{
			string text = Utils.RemoveClone(((Object)val).name);
			bool flag2 = LethalShipSort.Instance.vanillaItems.ContainsValue(text.ToLowerInvariant()) || LethalShipSort.Instance.modItems.ContainsValue(text.ToLowerInvariant());
			if (flag || !flag2)
			{
				string value = (((Object)(object)val.itemProperties != (Object)null) ? val.itemProperties.itemName : null);
				if (!dictionary.ContainsKey(text))
				{
					dictionary.Add(text, value);
				}
			}
		}
		if (dictionary.Count == 0)
		{
			return false;
		}
		string[] value2 = dictionary.Select((KeyValuePair<string, string> kvp) => kvp.Key + ((kvp.Value != null) ? (": " + kvp.Value) : "")).OrderBy<string, string>((string s) => s, StringComparer.CurrentCultureIgnoreCase).ToArray();
		string text2 = string.Join("\n", value2);
		string text3 = "The following" + (flag ? "" : " unknown") + " items are currently on the ship:\n";
		ChatCommandAPI.Print(text3 + "<indent=10px>" + text2 + "</indent>");
		LethalShipSort.Logger.LogInfo((object)(text3 + text2));
		return true;
	}
}
public class SetItemPositionCommand : Command
{
	public enum where
	{
		here,
		there,
		error
	}

	public enum when
	{
		once,
		game,
		always,
		error
	}

	[CompilerGenerated]
	private sealed class <SortItemsDelayed>d__15 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public uint delay;

		public GrabbableObject[] items;

		public Vector3 position;

		public GameObject relativeTo;

		public string errorPrefix;

		private int <itemsFailed>5__1;

		private string <error>5__2;

		private GrabbableObject[] <>s__3;

		private int <>s__4;

		private GrabbableObject <item>5__5;

		private Exception <e>5__6;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <SortItemsDelayed>d__15(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<error>5__2 = null;
			<>s__3 = null;
			<item>5__5 = null;
			<e>5__6 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<itemsFailed>5__1 = 0;
				<>s__3 = items;
				<>s__4 = 0;
				break;
			case 1:
				<>1__state = -1;
				<item>5__5 = null;
				<>s__4++;
				break;
			}
			if (<>s__4 < <>s__3.Length)
			{
				<item>5__5 = <>s__3[<>s__4];
				try
				{
					if (!Utils.MoveItem(<item>5__5, new ItemPosition
					{
						position = position,
						parentTo = relativeTo
					}))
					{
						<itemsFailed>5__1++;
					}
				}
				catch (Exception ex)
				{
					<e>5__6 = ex;
					LethalShipSort.Logger.LogError((object)<e>5__6);
					<itemsFailed>5__1++;
				}
				<>2__current = (object)new WaitForSeconds((float)delay / 1000f);
				<>1__state = 1;
				return true;
			}
			<>s__3 = null;
			<error>5__2 = <itemsFailed>5__1 + " items couldn't be sorted";
			if (<itemsFailed>5__1 != 0)
			{
				ChatCommandAPI.PrintError(errorPrefix + ": <noparse>" + <error>5__2 + "</noparse>");
			}
			else
			{
				ChatCommandAPI.Print("Finished sorting items");
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public override string Name => "SetItemPosition";

	public override string Description => "Sets the position for an item when sorting";

	public override string[] Commands => new string[2]
	{
		"put",
		((Command)this).Name
	};

	public override string[] Syntax => new string[1] { "\"<item>\" { here | there } [ once | game | always ]\nExample: /put \"easter egg\" there always" };

	public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
	{
		error = "The ship must be in orbit";
		return StartOfRound.Instance.inShipPhase && SetItemPosition(args, out error);
	}

	public static bool SetItemPosition(string[] args, out string error)
	{
		error = "Invalid arguments";
		Utils.objectCount.Clear();
		if (args == null)
		{
			return false;
		}
		if (args.Length == 2)
		{
			return SetItemPosition(args[0], ParseWhere(args[1]), when.once, out error);
		}
		if (args.Length == 3)
		{
			return SetItemPosition(args[0], ParseWhere(args[1]), ParseWhen(args[2]), out error);
		}
		return false;
	}

	private static where ParseWhere(string s)
	{
		if (s == null)
		{
			return where.error;
		}
		s = s.ToLowerInvariant();
		if (s == "here")
		{
			return where.here;
		}
		if (s == "there")
		{
			return where.there;
		}
		return where.error;
	}

	private static when ParseWhen(string s)
	{
		if (s == null)
		{
			return when.error;
		}
		s = s.ToLowerInvariant();
		if (s == "once" || s == "now")
		{
			return when.once;
		}
		if (s == "game" || s == "round")
		{
			return when.game;
		}
		if (s == "always" || s == "save")
		{
			return when.always;
		}
		return when.error;
	}

	public static bool SetItemPosition(string name, where where, when when, out string error)
	{
		//IL_037b: 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_0232: 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_03cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0529: Unknown result type (might be due to invalid IL or missing references)
		//IL_052e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0533: Unknown result type (might be due to invalid IL or missing references)
		//IL_033f: Unknown result type (might be due to invalid IL or missing references)
		error = "Invalid arguments";
		if (where == where.error || when == when.error)
		{
			return false;
		}
		error = "Invalid item name";
		if (!LethalShipSort.Instance.vanillaItems.TryGetValue(name.ToLowerInvariant(), out var internalName))
		{
			if (LethalShipSort.Instance.vanillaItems.ContainsValue(name.ToLowerInvariant()))
			{
				internalName = name;
			}
			else if (!LethalShipSort.Instance.modItems.TryGetValue(name.ToLowerInvariant(), out internalName))
			{
				if (!LethalShipSort.Instance.modItems.ContainsValue(name.ToLowerInvariant()))
				{
					return false;
				}
				internalName = name;
			}
		}
		LethalShipSort.Logger.LogDebug((object)("internalName: " + internalName + " (" + name + ")"));
		ConfigEntry<string> val = null;
		if (when == when.always)
		{
			if (!LethalShipSort.Instance.itemPositions.Keys.Any((string k) => string.Equals(k, internalName, StringComparison.CurrentCultureIgnoreCase)))
			{
				if (!LethalShipSort.Instance.modItemPositions.Keys.Any((string k) => string.Equals(k, internalName, StringComparison.CurrentCultureIgnoreCase)))
				{
					return false;
				}
				val = LethalShipSort.Instance.modItemPositions.First((KeyValuePair<string, ConfigEntry<string>> kvp) => string.Equals(kvp.Key, internalName, StringComparison.CurrentCultureIgnoreCase)).Value;
			}
			else
			{
				val = LethalShipSort.Instance.itemPositions.First((KeyValuePair<string, ConfigEntry<string>> kvp) => string.Equals(kvp.Key, internalName, StringComparison.CurrentCultureIgnoreCase)).Value;
			}
		}
		error = "Error getting position";
		if (!GetPosition(where, out var position, out var relativeTo))
		{
			return false;
		}
		Vector3 val2;
		switch (when)
		{
		case when.once:
		{
			string text4 = internalName;
			string? text5;
			if (!((Object)(object)relativeTo == (Object)null))
			{
				val2 = relativeTo.transform.InverseTransformPoint(position);
				text5 = ((object)(Vector3)(ref val2)).ToString();
			}
			else
			{
				text5 = ((object)(Vector3)(ref position)).ToString();
			}
			ChatCommandAPI.Print("Moving all items of type " + text4 + " to position " + text5);
			error = "No items to sort";
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			if (array == null)
			{
				return false;
			}
			array = array.Where((GrabbableObject i) => (Object)(object)i.playerHeldBy == (Object)null && !(i is RagdollGrabbableObject) && string.Equals(Utils.RemoveClone(((Object)i).name), internalName, StringComparison.CurrentCultureIgnoreCase)).ToArray();
			if (array.Length == 0)
			{
				return false;
			}
			if (LethalShipSort.Instance.SortDelay < 10)
			{
				int num = array.Count(delegate(GrabbableObject item)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					try
					{
						return !Utils.MoveItem(item, new ItemPosition
						{
							position = position,
							parentTo = relativeTo
						});
					}
					catch (Exception ex)
					{
						LethalShipSort.Logger.LogError((object)ex);
						return true;
					}
				});
				error = num + " items couldn't be sorted";
				ChatCommandAPI.Print("Finished sorting items");
				return num == 0;
			}
			if (SortItemsCommand.sorting != null)
			{
				((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StopCoroutine(SortItemsCommand.sorting);
			}
			SortItemsCommand.sorting = ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StartCoroutine(SortItemsDelayed(LethalShipSort.Instance.SortDelay, array, position, relativeTo));
			return true;
		}
		case when.game:
		{
			LethalShipSort.Instance.roundOverrides[internalName.ToLowerInvariant()] = Tuple.Create<Vector3, GameObject>(position, relativeTo);
			string[] obj = new string[5] { "Items of type ", internalName, " will be put on position ", null, null };
			string? text3;
			if (!((Object)(object)relativeTo == (Object)null))
			{
				val2 = relativeTo.transform.InverseTransformPoint(position);
				text3 = ((object)(Vector3)(ref val2)).ToString();
			}
			else
			{
				text3 = ((object)(Vector3)(ref position)).ToString();
			}
			obj[3] = text3;
			obj[4] = " for this game";
			ChatCommandAPI.Print(string.Concat(obj));
			goto case when.once;
		}
		case when.always:
		{
			if (val == null)
			{
				return false;
			}
			val.Value = (((Object)(object)relativeTo == (Object)null) ? ("none:" + position.x + "," + position.y + "," + position.z) : (Utils.GameObjectPath(relativeTo) + ":" + position.x + "," + position.y + "," + position.z));
			string text = internalName;
			string? text2;
			if (!((Object)(object)relativeTo == (Object)null))
			{
				val2 = relativeTo.transform.InverseTransformPoint(position);
				text2 = ((object)(Vector3)(ref val2)).ToString();
			}
			else
			{
				text2 = ((object)(Vector3)(ref position)).ToString();
			}
			ChatCommandAPI.Print("Items of type " + text + " will be put on position " + text2);
			goto case when.once;
		}
		default:
			return true;
		}
	}

	[IteratorStateMachine(typeof(<SortItemsDelayed>d__15))]
	private static IEnumerator SortItemsDelayed(uint delay, GrabbableObject[] items, Vector3 position, GameObject relativeTo, string errorPrefix = "Error running command")
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <SortItemsDelayed>d__15(0)
		{
			delay = delay,
			items = items,
			position = position,
			relativeTo = relativeTo,
			errorPrefix = errorPrefix
		};
	}

	private static bool GetPosition(where where, out Vector3 position, out GameObject relativeTo)
	{
		//IL_0002: 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_0034: 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_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: 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_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		position = default(Vector3);
		relativeTo = null;
		RaycastHit val = default(RaycastHit);
		switch (where)
		{
		case where.here:
			if (Physics.Raycast(((Component)GameNetworkManager.Instance.localPlayerController).transform.position, Vector3.down, ref val, 80f, 268437761, (QueryTriggerInteraction)1))
			{
				position = ((Component)((RaycastHit)(ref val)).collider).gameObject.transform.InverseTransformPoint(((RaycastHit)(ref val)).point + new Vector3(0f, 0.2f, 0f));
				relativeTo = ((Component)((RaycastHit)(ref val)).collider).gameObject;
				return true;
			}
			break;
		case where.there:
			if (Physics.Raycast(((Component)GameNetworkManager.Instance.localPlayerController.gameplayCamera).transform.position, ((Component)GameNetworkManager.Instance.localPlayerController.gameplayCamera).transform.forward, ref val, 80f, 268437761, (QueryTriggerInteraction)1))
			{
				position = ((Component)((RaycastHit)(ref val)).collider).gameObject.transform.InverseTransformPoint(((RaycastHit)(ref val)).point + new Vector3(0f, 0.2f, 0f));
				relativeTo = ((Component)((RaycastHit)(ref val)).collider).gameObject;
				return true;
			}
			break;
		}
		return false;
	}
}
public class SortItemsCommand : Command
{
	private enum ForceLevel
	{
		None,
		IncludeCruiser,
		IncludeAll
	}

	[HarmonyPatch(typeof(StartOfRound), "SetShipReadyToLand")]
	internal static class AutoSortPatch
	{
		private static void Prefix()
		{
			if (LethalShipSort.Instance.AutoSort && GameNetworkManager.Instance.localPlayerController.isHostPlayerObject)
			{
				AutoSortAllItems();
			}
		}
	}

	[CompilerGenerated]
	private sealed class <SortAllItemsDelayed>d__13 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public uint delay;

		public Dictionary<GrabbableObject, ItemPosition> scrap;

		public Dictionary<GrabbableObject, ItemPosition> tools;

		public string errorPrefix;

		private int <scrapFailed>5__1;

		private int <toolsFailed>5__2;

		private string <error>5__3;

		private Dictionary<GrabbableObject, ItemPosition>.Enumerator <>s__4;

		private KeyValuePair<GrabbableObject, ItemPosition> <kvp>5__5;

		private Exception <e>5__6;

		private Dictionary<GrabbableObject, ItemPosition>.Enumerator <>s__7;

		private KeyValuePair<GrabbableObject, ItemPosition> <kvp>5__8;

		private Exception <e>5__9;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <SortAllItemsDelayed>d__13(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			switch (<>1__state)
			{
			case -3:
			case 1:
				try
				{
				}
				finally
				{
					<>m__Finally1();
				}
				break;
			case -4:
			case 2:
				try
				{
				}
				finally
				{
					<>m__Finally2();
				}
				break;
			}
			<error>5__3 = null;
			<>s__4 = default(Dictionary<GrabbableObject, ItemPosition>.Enumerator);
			<kvp>5__5 = default(KeyValuePair<GrabbableObject, ItemPosition>);
			<e>5__6 = null;
			<>s__7 = default(Dictionary<GrabbableObject, ItemPosition>.Enumerator);
			<kvp>5__8 = default(KeyValuePair<GrabbableObject, ItemPosition>);
			<e>5__9 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			try
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<scrapFailed>5__1 = 0;
					<toolsFailed>5__2 = 0;
					<>s__4 = scrap.GetEnumerator();
					<>1__state = -3;
					goto IL_0116;
				case 1:
					<>1__state = -3;
					<kvp>5__5 = default(KeyValuePair<GrabbableObject, ItemPosition>);
					goto IL_0116;
				case 2:
					{
						<>1__state = -4;
						<kvp>5__8 = default(KeyValuePair<GrabbableObject, ItemPosition>);
						break;
					}
					IL_0116:
					if (<>s__4.MoveNext())
					{
						<kvp>5__5 = <>s__4.Current;
						try
						{
							if (!Utils.MoveItem(<kvp>5__5.Key, <kvp>5__5.Value))
							{
								<scrapFailed>5__1++;
							}
						}
						catch (Exception ex)
						{
							<e>5__6 = ex;
							LethalShipSort.Logger.LogError((object)<e>5__6);
							<scrapFailed>5__1++;
						}
						<>2__current = (object)new WaitForSeconds((float)delay / 1000f);
						<>1__state = 1;
						return true;
					}
					<>m__Finally1();
					<>s__4 = default(Dictionary<GrabbableObject, ItemPosition>.Enumerator);
					<>s__7 = tools.GetEnumerator();
					<>1__state = -4;
					break;
				}
				if (<>s__7.MoveNext())
				{
					<kvp>5__8 = <>s__7.Current;
					try
					{
						if (!Utils.MoveItem(<kvp>5__8.Key, <kvp>5__8.Value))
						{
							<toolsFailed>5__2++;
						}
					}
					catch (Exception ex)
					{
						<e>5__9 = ex;
						LethalShipSort.Logger.LogError((object)<e>5__9);
						<toolsFailed>5__2++;
					}
					<>2__current = (object)new WaitForSeconds((float)delay / 1000f);
					<>1__state = 2;
					return true;
				}
				<>m__Finally2();
				<>s__7 = default(Dictionary<GrabbableObject, ItemPosition>.Enumerator);
				<error>5__3 = ((<scrapFailed>5__1 > 0) ? (<scrapFailed>5__1 + " scrap items " + ((<toolsFailed>5__2 > 0) ? "and " : "")) : "") + ((<toolsFailed>5__2 > 0) ? (<toolsFailed>5__2 + " tool items") : "") + " couldn't be sorted";
				if (<scrapFailed>5__1 != 0 || <toolsFailed>5__2 != 0)
				{
					ChatCommandAPI.PrintError(errorPrefix + ": <noparse>" + <error>5__3 + "</noparse>");
				}
				else
				{
					ChatCommandAPI.Print("Finished sorting items");
				}
				return false;
			}
			catch
			{
				//try-fault
				((IDisposable)this).Dispose();
				throw;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		private void <>m__Finally1()
		{
			<>1__state = -1;
			((IDisposable)<>s__4).Dispose();
		}

		private void <>m__Finally2()
		{
			<>1__state = -1;
			((IDisposable)<>s__7).Dispose();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	internal static Coroutine sorting;

	public override string Name => "SortItems";

	public override string[] Commands => new string[3]
	{
		"sort",
		"ShipSort",
		((Command)this).Name
	};

	public override string Description => "Sorts all items on the ship\n-a: sort all items, even items on cruiser";

	public override string[] Syntax => new string[3] { "", "[ -a | -A ]", "<item> { here | there } [ once | game | always ]" };

	public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
	{
		error = "The ship must be in orbit";
		if (!StartOfRound.Instance.inShipPhase)
		{
			return false;
		}
		if (args.Length < 2)
		{
			ForceLevel forceLevel = ForceLevel.None;
			if (args.Contains("-A") || args.Contains<string>("--all", StringComparer.InvariantCultureIgnoreCase))
			{
				forceLevel = ForceLevel.IncludeAll;
			}
			else if (args.Contains("-a"))
			{
				forceLevel = ForceLevel.IncludeCruiser;
			}
			return SortAllItems(forceLevel, out error);
		}
		return SetItemPositionCommand.SetItemPosition(args, out error);
	}

	private static bool SortAllItems(ForceLevel forceLevel, out string error)
	{
		error = "No items to sort";
		Utils.objectCount.Clear();
		GameNetworkManager.Instance.localPlayerController.DropAllHeldItemsAndSync();
		GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
		if (array == null)
		{
			return false;
		}
		array = array.Where((GrabbableObject i) => (Object)(object)i.playerHeldBy == (Object)null && !(i is RagdollGrabbableObject)).ToArray();
		if (array.Length == 0)
		{
			return false;
		}
		ChatCommandAPI.Print("Sorting all items...");
		VehicleController[] cars = (VehicleController[])(((object)Object.FindObjectsOfType<VehicleController>()) ?? ((object)new VehicleController[0]));
		Dictionary<GrabbableObject, ItemPosition> dictionary = FilterFlags(array.Where((GrabbableObject i) => i.itemProperties.isScrap).ToDictionary((GrabbableObject i) => i, (GrabbableObject item) => LethalShipSort.Instance.GetPosition(item)));
		Dictionary<GrabbableObject, ItemPosition> dictionary2 = FilterFlags(array.Where((GrabbableObject i) => !i.itemProperties.isScrap).ToDictionary((GrabbableObject i) => i, (GrabbableObject item) => LethalShipSort.Instance.GetPosition(item)));
		if (LethalShipSort.Instance.SortDelay < 10)
		{
			int num = 0;
			int num2 = 0;
			if (dictionary.Count != 0)
			{
				num = SortItems(dictionary);
			}
			if (dictionary2.Count != 0)
			{
				num2 = SortItems(dictionary2);
			}
			error = ((num > 0) ? (num + " scrap items " + ((num2 > 0) ? "and " : "")) : "") + ((num2 > 0) ? (num2 + " tool items") : "") + " couldn't be sorted";
			if (num != 0 || num2 != 0)
			{
				return false;
			}
			ChatCommandAPI.Print("Finished sorting items");
		}
		else
		{
			if (sorting != null)
			{
				((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StopCoroutine(sorting);
			}
			sorting = ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StartCoroutine(SortAllItemsDelayed(LethalShipSort.Instance.SortDelay, dictionary, dictionary2));
		}
		return true;
		Dictionary<GrabbableObject, ItemPosition> FilterFlags(Dictionary<GrabbableObject, ItemPosition> dict)
		{
			return dict.Where((KeyValuePair<GrabbableObject, ItemPosition> kvp) => (forceLevel == ForceLevel.IncludeAll || !kvp.Value.flags.Ignore) && (forceLevel >= ForceLevel.IncludeCruiser || !kvp.Value.flags.KeepOnCruiser || !cars.Any((VehicleController car) => (Object)(object)((Component)kvp.Key).transform.parent == (Object)(object)((Component)car).transform))).ToDictionary((KeyValuePair<GrabbableObject, ItemPosition> kvp) => kvp.Key, (KeyValuePair<GrabbableObject, ItemPosition> kvp) => kvp.Value);
		}
	}

	private static void AutoSortAllItems()
	{
		try
		{
			Utils.objectCount.Clear();
			GameNetworkManager.Instance.localPlayerController.DropAllHeldItemsAndSync();
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			if (array == null)
			{
				return;
			}
			array = array.Where((GrabbableObject i) => (Object)(object)i.playerHeldBy == (Object)null && !(i is RagdollGrabbableObject)).ToArray();
			if (array.Length == 0)
			{
				return;
			}
			ChatCommandAPI.Print("Sorting all items...");
			VehicleController[] cars = (VehicleController[])(((object)Object.FindObjectsOfType<VehicleController>()) ?? ((object)new VehicleController[0]));
			Dictionary<GrabbableObject, ItemPosition> dictionary = FilterFlags(array.Where((GrabbableObject i) => i.itemProperties.isScrap).ToDictionary((GrabbableObject i) => i, (GrabbableObject item) => LethalShipSort.Instance.GetPosition(item)));
			Dictionary<GrabbableObject, ItemPosition> dictionary2 = FilterFlags(array.Where((GrabbableObject i) => !i.itemProperties.isScrap).ToDictionary((GrabbableObject i) => i, (GrabbableObject item) => LethalShipSort.Instance.GetPosition(item)));
			if (LethalShipSort.Instance.SortDelay < 10)
			{
				int num = 0;
				int num2 = 0;
				if (dictionary.Count != 0)
				{
					num = SortItems(dictionary);
				}
				if (dictionary2.Count != 0)
				{
					num2 = SortItems(dictionary2);
				}
				if (num != 0 || num2 != 0)
				{
					ChatCommandAPI.PrintError("Automatic sorting failed: " + ((num > 0) ? (num + " scrap items " + ((num2 > 0) ? "and " : "")) : "") + ((num2 > 0) ? (num2 + " tool items") : "") + " couldn't be sorted");
				}
				else
				{
					ChatCommandAPI.Print("Finished sorting items");
				}
			}
			else
			{
				if (sorting != null)
				{
					((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StopCoroutine(sorting);
				}
				sorting = ((MonoBehaviour)GameNetworkManager.Instance.localPlayerController).StartCoroutine(SortAllItemsDelayed(LethalShipSort.Instance.SortDelay, dictionary, dictionary2, "Automatic sorting failed"));
			}
			Dictionary<GrabbableObject, ItemPosition> FilterFlags(Dictionary<GrabbableObject, ItemPosition> dict)
			{
				return dict.Where((KeyValuePair<GrabbableObject, ItemPosition> kvp) => !kvp.Value.flags.Ignore && !kvp.Value.flags.NoAutoSort && (!kvp.Value.flags.KeepOnCruiser || !cars.Any((VehicleController car) => (Object)(object)((Component)kvp.Key).transform.parent == (Object)(object)((Component)car).transform))).ToDictionary((KeyValuePair<GrabbableObject, ItemPosition> kvp) => kvp.Key, (KeyValuePair<GrabbableObject, ItemPosition> kvp) => kvp.Value);
			}
		}
		catch (Exception ex)
		{
			ChatCommandAPI.PrintError("Automatic sorting failed due to an internal error, check the log for details");
			LethalShipSort.Logger.LogError((object)("Error while autosorting items: " + ex));
		}
	}

	[IteratorStateMachine(typeof(<SortAllItemsDelayed>d__13))]
	public static IEnumerator SortAllItemsDelayed(uint delay, Dictionary<GrabbableObject, ItemPosition> scrap, Dictionary<GrabbableObject, ItemPosition> tools, string errorPrefix = "Error running command")
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <SortAllItemsDelayed>d__13(0)
		{
			delay = delay,
			scrap = scrap,
			tools = tools,
			errorPrefix = errorPrefix
		};
	}

	public static int SortItems(Dictionary<GrabbableObject, ItemPosition> items)
	{
		return items.Count(delegate(KeyValuePair<GrabbableObject, ItemPosition> kvp)
		{
			try
			{
				return !Utils.MoveItem(kvp.Key, kvp.Value);
			}
			catch (Exception ex)
			{
				LethalShipSort.Logger.LogError((object)ex);
				return true;
			}
		});
	}
}
public static class Utils
{
	private const string CLONE = "(Clone)";

	internal static readonly Dictionary<string, int> objectCount = new Dictionary<string, int>();

	internal const int LAYER_MASK = 268437761;

	public static IReadOnlyDictionary<string, int> ObjectCount => objectCount;

	public static string RemoveClone(string name)
	{
		if (name != null && name.EndsWith("(Clone)"))
		{
			return name.Substring(0, name.Length - "(Clone)".Length);
		}
		return name;
	}

	public static bool MoveItem(GrabbableObject item, ItemPosition position)
	{
		//IL_0044: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		if (!position.position.HasValue)
		{
			throw new ArgumentNullException("ItemPosition.position can not be null");
		}
		int itemCount = GetItemCount(item);
		Vector3 positionOffset = (position.positionOffset.HasValue ? (position.positionOffset.Value * (float)itemCount) : Vector3.zero);
		int floorYRot = position.floorYRot.GetValueOrDefault(-1) + position.rotationOffset.GetValueOrDefault() * itemCount % 360;
		return ((position.flags.Parent && (Object)(object)position.parentTo != (Object)null) ? MoveItem(item, position.position.Value, positionOffset, position.parentTo, floorYRot, position.randomOffset, position.flags) : MoveItemRelativeTo(item, position.position.Value, positionOffset, position.parentTo, floorYRot, position.randomOffset, position.flags)) && IncreaseItemCount(item);
	}

	private static bool IncreaseItemCount(GrabbableObject item)
	{
		string key = ItemKey(item);
		objectCount.TryGetValue(key, out var value);
		objectCount[key] = value + 1;
		return true;
	}

	private static int GetItemCount(GrabbableObject item)
	{
		objectCount.TryGetValue(ItemKey(item), out var value);
		return value;
	}

	public static string ItemKey(GrabbableObject item)
	{
		ShotgunItem val = (ShotgunItem)(object)((item is ShotgunItem) ? item : null);
		if ((Object)(object)val != (Object)null && val.shellsLoaded > 0)
		{
			return "ShotgunItem-" + Math.Min(val.shellsLoaded, 2);
		}
		return RemoveClone(((Object)item).name);
	}

	public static bool MoveItemRelativeTo(GrabbableObject item, Vector3 position, Vector3 positionOffset, GameObject relativeTo, int floorYRot, float? randomOffset, ItemPosition.Flags flags)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: 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_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: 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_0101: 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)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: 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_0116: 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)
		ManualLogSource logger = LethalShipSort.Logger;
		string[] obj = new string[6]
		{
			">> Moving item ",
			RemoveClone(((Object)item).name),
			" to position ",
			null,
			null,
			null
		};
		Vector3 val = position;
		obj[3] = ((object)(Vector3)(ref val)).ToString();
		obj[4] = " relative to ";
		obj[5] = (((Object)(object)relativeTo == (Object)null) ? "ship" : RemoveClone(((Object)relativeTo).name));
		logger.LogInfo((object)string.Concat(obj));
		GameObject val2 = GameObject.Find("Environment/HangarShip");
		if ((Object)(object)val2 == (Object)null)
		{
			LethalShipSort.Logger.LogWarning((object)"   Couldn't find ship");
			return false;
		}
		if ((Object)(object)relativeTo == (Object)null)
		{
			relativeTo = val2;
		}
		if (!flags.Exact)
		{
			RaycastHit val3 = default(RaycastHit);
			if (!Physics.Raycast(relativeTo.transform.TransformPoint(position), Vector3.down, ref val3, 80f, 268437761, (QueryTriggerInteraction)1))
			{
				LethalShipSort.Logger.LogWarning((object)"   Raycast unsuccessful");
				return false;
			}
			position = Randomize(val2.transform.InverseTransformPoint(((RaycastHit)(ref val3)).point + item.itemProperties.verticalOffset * Vector3.up + positionOffset), randomOffset);
		}
		else
		{
			position = Randomize(position + item.itemProperties.verticalOffset * Vector3.up + positionOffset, randomOffset);
		}
		ManualLogSource logger2 = LethalShipSort.Logger;
		val = position;
		logger2.LogDebug((object)("   true position: " + ((object)(Vector3)(ref val)).ToString()));
		GameNetworkManager.Instance.localPlayerController.SetObjectAsNoLongerHeld(true, true, position, item, floorYRot);
		return true;
	}

	public static bool MoveItem(GrabbableObject item, Vector3 position, Vector3 positionOffset, GameObject parentTo, int floorYRot, float? randomOffset, ItemPosition.Flags flags)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: 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_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		ManualLogSource logger = LethalShipSort.Logger;
		string[] obj = new string[6]
		{
			">> Moving item ",
			RemoveClone(((Object)item).name),
			" to position ",
			null,
			null,
			null
		};
		Vector3 val = position;
		obj[3] = ((object)(Vector3)(ref val)).ToString();
		obj[4] = " in ";
		obj[5] = RemoveClone(((Object)parentTo).name);
		logger.LogInfo((object)string.Concat(obj));
		if (!flags.Exact)
		{
			RaycastHit val2 = default(RaycastHit);
			if (!Physics.Raycast(parentTo.transform.TransformPoint(position), Vector3.down, ref val2, 80f, 268437761, (QueryTriggerInteraction)1))
			{
				LethalShipSort.Logger.LogWarning((object)"   Raycast unsuccessful");
				return false;
			}
			position = parentTo.transform.InverseTransformPoint(Randomize(((RaycastHit)(ref val2)).point + item.itemProperties.verticalOffset * Vector3.up - new Vector3(0f, 0.05f, 0f) + positionOffset, randomOffset));
		}
		else
		{
			position = Randomize(position + item.itemProperties.verticalOffset * Vector3.up - new Vector3(0f, 0.05f, 0f) + positionOffset, randomOffset);
		}
		ManualLogSource logger2 = LethalShipSort.Logger;
		val = position;
		logger2.LogDebug((object)("   true position: " + ((object)(Vector3)(ref val)).ToString()));
		GameNetworkManager.Instance.localPlayerController.SetObjectAsNoLongerHeld(true, true, position, item, floorYRot);
		GameNetworkManager.Instance.localPlayerController.PlaceGrabbableObject(parentTo.transform, position, false, item);
		return true;
	}

	public static Vector3 Randomize(Vector3 position, float? maxDistance = null)
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: 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_00ab: 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_004e: 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)
		if (maxDistance < 0f)
		{
			throw new ArgumentException("Invalid randomOffset (must be positive)");
		}
		if (!maxDistance.HasValue || Mathf.Approximately(maxDistance.Value, 0f))
		{
			return position;
		}
		Random random = new Random();
		return new Vector3(position.x + (float)random.NextDouble() * maxDistance.Value * 2f - maxDistance.Value, position.y, position.z + (float)random.NextDouble() * maxDistance.Value * 2f - maxDistance.Value);
	}

	public static string GameObjectPath(GameObject gameObject)
	{
		Transform parent = gameObject.transform.parent;
		string text = ((Object)gameObject).name;
		while ((Object)(object)parent != (Object)null)
		{
			text = ((Object)parent).name + "/" + text;
			parent = ((Component)parent).transform.parent;
		}
		return text;
	}
}