Decompiled source of SlotSort v1.2.0

SlotSort.dll

Decompiled 20 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppSystem.Collections.Generic;
using ProjectM;
using ProjectM.Network;
using ProjectM.Scripting;
using SlotSort.Commands.Converters;
using SlotSort.Models;
using SlotSort.Services;
using SlotSort.Ui;
using Stunlock.Core;
using Unity.Collections;
using Unity.Entities;
using Unity.Scenes;
using VampireCommandFramework;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("SlotSort")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Custom inventory slot sorting on sort button")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("SlotSort")]
[assembly: AssemblyTitle("SlotSort")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.0")]
[module: UnverifiableCode]
namespace SlotSort
{
	internal static class Core
	{
		private static bool hasInitialized;

		public static World Server { get; } = GetWorld("Server") ?? throw new Exception("Server world not found. Install this mod on the dedicated server.");

		public static EntityManager EntityManager { get; } = Server.EntityManager;

		public static PrefabCollectionSystem PrefabCollectionSystem { get; private set; } = null;

		public static ServerScriptMapper ServerScriptMapper { get; private set; } = null;

		public static ServerGameManager ServerGameManager => ServerScriptMapper.GetServerGameManager();

		public static SlotAssignmentService SlotAssignments { get; } = new SlotAssignmentService();

		public static InventorySlotService InventorySlots { get; } = new InventorySlotService();

		public static SlotSortUiService Ui { get; } = new SlotSortUiService();

		public static ManualLogSource Log => Plugin.LogInstance;

		public static bool HasInitialized => hasInitialized;

		public static void Initialize()
		{
			if (!hasInitialized)
			{
				PrefabCollectionSystem = Server.GetExistingSystemManaged<PrefabCollectionSystem>();
				ServerScriptMapper = Server.GetExistingSystemManaged<ServerScriptMapper>();
				SlotAssignments.LoadDefaults();
				SlotAssignments.LoadAllPlayers();
				hasInitialized = true;
				Log.LogInfo((object)"SlotSort initialized");
			}
		}

		private static World GetWorld(string name)
		{
			Enumerator<World> enumerator = World.s_AllWorlds.GetEnumerator();
			while (enumerator.MoveNext())
			{
				World current = enumerator.Current;
				if (current.Name == name)
				{
					return current;
				}
			}
			return null;
		}

		public static void LogException(Exception e, string context)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(4, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(context);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(e.Message);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\n");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(e.StackTrace);
			}
			log.LogError(val);
		}
	}
	internal static class ECSExtensions
	{
		private static EntityManager EntityManager => Core.EntityManager;

		public unsafe static void Write<T>(this Entity entity, T componentData) where T : struct
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			ComponentType val = default(ComponentType);
			((ComponentType)(ref val))..ctor(Il2CppType.Of<T>(), (AccessMode)0);
			byte[] array = StructureToByteArray(componentData);
			int num = Marshal.SizeOf<T>();
			fixed (byte* ptr = array)
			{
				EntityManager entityManager = EntityManager;
				((EntityManager)(ref entityManager)).SetComponentDataRaw(entity, val.TypeIndex, (void*)ptr, num);
			}
		}

		private static byte[] StructureToByteArray<T>(T structure) where T : struct
		{
			int num = Marshal.SizeOf(structure);
			byte[] array = new byte[num];
			IntPtr intPtr = Marshal.AllocHGlobal(num);
			Marshal.StructureToPtr(structure, intPtr, fDeleteOld: true);
			Marshal.Copy(intPtr, array, 0, num);
			Marshal.FreeHGlobal(intPtr);
			return array;
		}

		public unsafe static T Read<T>(this Entity entity) where T : struct
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			ComponentType val = default(ComponentType);
			((ComponentType)(ref val))..ctor(Il2CppType.Of<T>(), (AccessMode)0);
			EntityManager entityManager = EntityManager;
			return Marshal.PtrToStructure<T>(new IntPtr(((EntityManager)(ref entityManager)).GetComponentDataRawRO(entity, val.TypeIndex)));
		}

		public static DynamicBuffer<T> ReadBuffer<T>(this Entity entity) where T : struct
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			EntityManager entityManager = EntityManager;
			return ((EntityManager)(ref entityManager)).GetBuffer<T>(entity, false);
		}

		public static bool Has<T>(this Entity entity) where T : struct
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//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)
			ComponentType val = default(ComponentType);
			((ComponentType)(ref val))..ctor(Il2CppType.Of<T>(), (AccessMode)0);
			EntityManager entityManager = EntityManager;
			return ((EntityManager)(ref entityManager)).HasComponent(entity, val);
		}

		public static string PrefabName(this PrefabGUID prefabGuid)
		{
			//IL_001a: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			Enumerator<string, PrefabGUID> enumerator = Core.PrefabCollectionSystem._SpawnableNameToPrefabGuidDictionary.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<string, PrefabGUID> current = enumerator.Current;
				PrefabGUID value = current.Value;
				if (((PrefabGUID)(ref value)).Equals(prefabGuid))
				{
					return current.Key;
				}
			}
			return $"Unknown ({((PrefabGUID)(ref prefabGuid)).GuidHash})";
		}

		public static string LookupName(this PrefabGUID prefabGuid)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return prefabGuid.PrefabName();
		}
	}
	[BepInPlugin("SlotSort", "SlotSort", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		private static Plugin instance;

		private Harmony harmony;

		public static Harmony Harmony => instance.harmony;

		public static ManualLogSource LogInstance => ((BasePlugin)instance).Log;

		public override void Load()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			instance = this;
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(24, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("SlotSort");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" version ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.1.1");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded.");
			}
			log.LogInfo(val);
			harmony = new Harmony("SlotSort");
			harmony.PatchAll(typeof(Plugin).Assembly);
			CommandRegistry.RegisterAll();
		}

		public override bool Unload()
		{
			CommandRegistry.UnregisterAssembly();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			return true;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "SlotSort";

		public const string PLUGIN_NAME = "SlotSort";

		public const string PLUGIN_VERSION = "1.1.1";
	}
}
namespace SlotSort.Ui
{
	internal sealed class SlotSortUiService
	{
		private readonly ZuiPacketService packets = new ZuiPacketService();

		private static readonly (string Label, string ItemQuery, int Slot)[] QuickPresets = new(string, string, int)[5]
		{
			("Blood Rose -> slot 9", "BloodRose", 9),
			("Blood Potion -> slot 10", "BloodPotion", 10),
			("Cloak -> slot 11", "Cloak", 11),
			("Vermin Salve -> slot 12", "VerminSalve", 12),
			("Wolf Pelt -> slot 13", "WolfPelt", 13)
		};

		public void Open(User user, ulong steamId)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00d1: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			bool enabled = Core.SlotAssignments.IsEnabled(steamId);
			IReadOnlyList<SlotAssignmentEntry> assignments = Core.SlotAssignments.GetAssignments(steamId);
			packets.Send(user, "SetPlugin", new Dictionary<string, string> { { "Plugin", "SlotSort" } });
			packets.Send(user, "SetTargetWindow", new Dictionary<string, string> { { "Window", "SlotSortPanel" } });
			packets.Send(user, "SetUICustom", new Dictionary<string, string>
			{
				{ "W", "640" },
				{ "H", "560" }
			});
			packets.Send(user, "SetTitle", new Dictionary<string, string> { { "Text", "<color=#9B59B6>SlotSort</color> — fixed inventory slots" } });
			BuildMainTab(user, enabled);
			BuildRulesTab(user, assignments);
			BuildAddTab(user);
			BuildSearchTab(user, steamId);
			packets.Send(user, "Open", new Dictionary<string, string>());
		}

		private void BuildMainTab(User user, bool enabled)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_0126: 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_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			packets.Send(user, "CreateTab", new Dictionary<string, string> { { "Name", "Main" } });
			string text = (enabled ? "<color=#2ECC71>Enabled</color>" : "<color=#E74C3C>Disabled</color>");
			packets.Send(user, "AddText", new Dictionary<string, string>
			{
				{
					"Text",
					"Status: " + text
				},
				{ "X", "20" },
				{ "Y", "20" }
			});
			packets.Send(user, "AddText", new Dictionary<string, string>
			{
				{
					"Text",
					$"Slots 1-{8} = hotbar, {9}+ = bag. Press Sort to apply."
				},
				{ "X", "20" },
				{ "Y", "50" }
			});
			AddButton(user, "Toggle on/off", ".slotsort toggle", 20, 90, 600, 36);
			AddButton(user, "Apply slots now", ".slotsort sort", 20, 136, 600, 36);
			AddButton(user, "Refresh window", ".slotsort gui", 20, 182, 600, 36);
			packets.Send(user, "AddCategory", new Dictionary<string, string>
			{
				{ "Name", "<color=#3498DB>How it works</color>" },
				{ "X", "20" },
				{ "Y", "240" }
			});
			packets.Send(user, "AddText", new Dictionary<string, string>
			{
				{ "Text", "1) Add rules on the Add tab\n2) Press Sort in inventory\n3) Items move to your chosen slots" },
				{ "X", "20" },
				{ "Y", "270" }
			});
			packets.Send(user, "AddText", new Dictionary<string, string>
			{
				{ "Text", "<color=#95A5A6>Requires ZUI client mod (Zanakinz/ZUI)</color>" },
				{ "X", "20" },
				{ "Y", "360" }
			});
		}

		private void BuildRulesTab(User user, IReadOnlyList<SlotAssignmentEntry> assignments)
		{
			//IL_0006: 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_007a: 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_0158: 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)
			packets.Send(user, "CreateTab", new Dictionary<string, string> { { "Name", "Rules" } });
			packets.Send(user, "AddText", new Dictionary<string, string>
			{
				{ "Text", "Active slot rules:" },
				{ "X", "20" },
				{ "Y", "20" }
			});
			if (assignments.Count == 0)
			{
				packets.Send(user, "AddText", new Dictionary<string, string>
				{
					{ "Text", "<color=#F39C12>No rules yet. Use the Add tab.</color>" },
					{ "X", "20" },
					{ "Y", "55" }
				});
				return;
			}
			int num = 55;
			int num2 = 0;
			foreach (SlotAssignmentEntry assignment in assignments)
			{
				if (num2 >= 10)
				{
					packets.Send(user, "AddText", new Dictionary<string, string>
					{
						{ "Text", "<color=#95A5A6>...and more. Use .slotsort list</color>" },
						{ "X", "20" },
						{
							"Y",
							num.ToString()
						}
					});
					break;
				}
				string displayName = GetDisplayName(assignment);
				string value = ((displayName.Length > 42) ? (displayName.Substring(0, 39) + "...") : displayName);
				packets.Send(user, "AddText", new Dictionary<string, string>
				{
					{
						"Text",
						$"<color=#F1C40F>Slot {assignment.Slot}</color>  {value}"
					},
					{ "X", "20" },
					{
						"Y",
						num.ToString()
					}
				});
				AddButton(user, "X", $".slotsort rmid {assignment.ItemGuid}", 560, num - 4, 50, 28);
				num += 42;
				num2++;
			}
		}

		private void BuildAddTab(User user)
		{
			//IL_0006: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_009d: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
			packets.Send(user, "CreateTab", new Dictionary<string, string> { { "Name", "Add" } });
			packets.Send(user, "AddCategory", new Dictionary<string, string>
			{
				{ "Name", "<color=#2ECC71>Quick presets</color>" },
				{ "X", "20" },
				{ "Y", "20" }
			});
			int num = 55;
			(string, string, int)[] quickPresets = QuickPresets;
			for (int i = 0; i < quickPresets.Length; i++)
			{
				(string, string, int) tuple = quickPresets[i];
				PrefabGUID val = InventorySlotService.ResolveItemGuidByName(tuple.Item2);
				if (((PrefabGUID)(ref val)).GuidHash != 0)
				{
					AddButton(user, tuple.Item1, $".slotsort setid {((PrefabGUID)(ref val)).GuidHash} {tuple.Item3}", 20, num, 600, 34);
					num += 42;
				}
			}
			packets.Send(user, "AddCategory", new Dictionary<string, string>
			{
				{ "Name", "<color=#3498DB>Pick a bag slot (9-16)</color>" },
				{ "X", "20" },
				{
					"Y",
					(num + 10).ToString()
				}
			});
			num += 45;
			int num2 = 0;
			for (int j = 9; j <= 16; j++)
			{
				int x = 20 + num2 * 74;
				AddButton(user, j.ToString(), $".slotsort pickslot {j}", x, num, 68, 32);
				num2++;
			}
			packets.Send(user, "AddText", new Dictionary<string, string>
			{
				{ "Text", "Pick slot, then chat: .slotsort setheld\nOr: .slotsort set \"item name\" 12\nOr: .slotsort search blood" },
				{ "X", "20" },
				{
					"Y",
					(num + 45).ToString()
				}
			});
		}

		private void BuildSearchTab(User user, ulong steamId)
		{
			//IL_0006: 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_00ba: 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)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: 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_0313: Unknown result type (might be due to invalid IL or missing references)
			packets.Send(user, "CreateTab", new Dictionary<string, string> { { "Name", "Search" } });
			packets.Send(user, "AddText", new Dictionary<string, string>
			{
				{ "Text", "Chat: <color=#F1C40F>.slotsort search blood</color> (or any part of the item name)" },
				{ "X", "20" },
				{ "Y", "20" }
			});
			int slot;
			string value = (Core.SlotAssignments.TryGetPendingSlot(steamId, out slot) ? $"<color=#2ECC71>Selected slot: {slot}</color>" : "<color=#F39C12>Pick a slot below before assigning</color>");
			packets.Send(user, "AddText", new Dictionary<string, string>
			{
				{ "Text", value },
				{ "X", "20" },
				{ "Y", "50" }
			});
			int num = 80;
			for (int i = 9; i <= 16; i++)
			{
				int x = 20 + (i - 9) * 74;
				AddButton(user, i.ToString(), $".slotsort pickslot {i}", x, num, 68, 32);
			}
			num += 45;
			if (!Core.SlotAssignments.TryGetSearchResults(steamId, out var query, out var itemGuids) || itemGuids.Count == 0)
			{
				packets.Send(user, "AddText", new Dictionary<string, string>
				{
					{ "Text", "<color=#95A5A6>No search yet. Run .slotsort search in chat.</color>" },
					{ "X", "20" },
					{
						"Y",
						num.ToString()
					}
				});
				return;
			}
			packets.Send(user, "AddCategory", new Dictionary<string, string>
			{
				{
					"Name",
					"<color=#3498DB>Results for \"" + query + "\"</color>"
				},
				{ "X", "20" },
				{
					"Y",
					num.ToString()
				}
			});
			num += 35;
			int num2 = 0;
			foreach (int item in itemGuids)
			{
				if (num2 >= 8)
				{
					packets.Send(user, "AddText", new Dictionary<string, string>
					{
						{
							"Text",
							$"<color=#95A5A6>...and {itemGuids.Count - 8} more. Refine your search.</color>"
						},
						{ "X", "20" },
						{
							"Y",
							num.ToString()
						}
					});
					break;
				}
				string text = ItemSearchService.FormatDisplayName(ECSExtensions.PrefabName(new PrefabGUID(item)));
				if (text.Length > 36)
				{
					text = text.Substring(0, 33) + "...";
				}
				string cmd = $".slotsort setid {item}";
				AddButton(user, text, cmd, 20, num, 520, 34);
				num += 42;
				num2++;
			}
		}

		private static string GetDisplayName(SlotAssignmentEntry entry)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (entry.ItemGuid != 0)
			{
				return ECSExtensions.PrefabName(new PrefabGUID(entry.ItemGuid));
			}
			return entry.ItemName;
		}

		private void AddButton(User user, string text, string cmd, int x, int y, int w, int h)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			packets.Send(user, "AddButton", new Dictionary<string, string>
			{
				{ "Text", text },
				{ "Cmd", cmd },
				{
					"X",
					x.ToString()
				},
				{
					"Y",
					y.ToString()
				},
				{
					"W",
					w.ToString()
				},
				{
					"H",
					h.ToString()
				}
			});
		}
	}
	internal sealed class ZuiPacketService
	{
		public const string PluginName = "SlotSort";

		public const string WindowName = "SlotSortPanel";

		public void Send(User user, string type, Dictionary<string, string> data)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			string text = JsonSerializer.Serialize(new
			{
				Type = type,
				Plugin = "SlotSort",
				Window = "SlotSortPanel",
				Data = data
			});
			string text2 = "[[ZUI]]" + text;
			if (text2.Length >= 511)
			{
				ManualLogSource log = Core.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(30, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ZUI packet too long (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(text2.Length);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" chars): ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(type);
				}
				log.LogWarning(val);
			}
			else
			{
				ServerChatUtils.SendSystemMessageToClient(Core.EntityManager, user, text2);
			}
		}
	}
}
namespace SlotSort.Services
{
	internal sealed class InventorySlotService
	{
		public const int HotbarSlots = 8;

		public void ApplyAssignments(Entity character, ulong steamId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			//IL_006a: 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_006f: 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_0095: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			Entity val = default(Entity);
			if (!InventoryUtilities.TryGetInventoryEntity(Core.EntityManager, character, ref val, 0))
			{
				return;
			}
			ServerGameManager serverGameManager = Core.ServerGameManager;
			DynamicBuffer<InventoryBuffer> buffer = default(DynamicBuffer<InventoryBuffer>);
			if (!((ServerGameManager)(ref serverGameManager)).TryGetBuffer<InventoryBuffer>(val, ref buffer))
			{
				return;
			}
			IReadOnlyList<SlotAssignmentEntry> assignments = Core.SlotAssignments.GetAssignments(steamId);
			if (assignments.Count == 0)
			{
				return;
			}
			foreach (SlotAssignmentEntry item in assignments)
			{
				PrefabGUID itemGuid = (PrefabGUID)((item.ItemGuid != 0) ? new PrefabGUID(item.ItemGuid) : ResolveItemGuid(item.ItemName));
				if (((PrefabGUID)(ref itemGuid)).GuidHash != 0)
				{
					int num = ToBufferIndex(item.Slot, buffer.Length);
					if (num >= 0 && TryFindItemSlot(buffer, itemGuid, num, out var sourceIndex) && sourceIndex != num)
					{
						SwapSlots(val, buffer, sourceIndex, num);
					}
				}
			}
		}

		public static PrefabGUID ResolveItemGuidByName(string itemName)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrWhiteSpace(itemName))
			{
				return PrefabGUID.Empty;
			}
			if (ItemSearchService.TryResolveExact(itemName, out var prefab))
			{
				return prefab;
			}
			List<ItemSearchService.ItemMatch> list = ItemSearchService.FindItems(itemName, 2);
			if (list.Count != 1)
			{
				return PrefabGUID.Empty;
			}
			return list[0].Guid;
		}

		private static PrefabGUID ResolveItemGuid(string itemName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return ResolveItemGuidByName(itemName);
		}

		private static int ToBufferIndex(int slotNumber, int bufferLength)
		{
			int num = slotNumber - 1;
			if (num < 0 || num >= bufferLength)
			{
				return -1;
			}
			return num;
		}

		private static bool TryFindItemSlot(DynamicBuffer<InventoryBuffer> buffer, PrefabGUID itemGuid, int skipIndex, out int sourceIndex)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < buffer.Length; i++)
			{
				if (i != skipIndex)
				{
					InventoryBuffer val = buffer[i];
					if (val.Amount > 0 && ((PrefabGUID)(ref val.ItemType)).Equals(itemGuid))
					{
						sourceIndex = i;
						return true;
					}
				}
			}
			sourceIndex = -1;
			return false;
		}

		private static void SwapSlots(Entity inventory, DynamicBuffer<InventoryBuffer> buffer, int sourceIndex, int targetIndex)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			InventoryBuffer val = buffer[sourceIndex];
			InventoryBuffer entry = (buffer[sourceIndex] = buffer[targetIndex]);
			buffer[targetIndex] = val;
			UpdateItemEntityContainer(val, inventory);
			UpdateItemEntityContainer(entry, inventory);
		}

		private static void UpdateItemEntityContainer(InventoryBuffer entry, Entity inventory)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			Entity entityOnServer = ((NetworkedEntity)(ref entry.ItemEntity)).GetEntityOnServer();
			if (!((Entity)(ref entityOnServer)).Equals(Entity.Null) && entityOnServer.Has<InventoryItem>())
			{
				InventoryItem componentData = entityOnServer.Read<InventoryItem>();
				componentData.ContainerEntity = inventory;
				entityOnServer.Write<InventoryItem>(componentData);
			}
		}
	}
	internal static class ItemSearchService
	{
		public readonly record struct ItemMatch(PrefabGUID Guid, string PrefabName);

		public static bool TryResolveExact(string query, out PrefabGUID prefab)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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)
			Enumerator<string, PrefabGUID> enumerator = Core.PrefabCollectionSystem._SpawnableNameToPrefabGuidDictionary.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<string, PrefabGUID> current = enumerator.Current;
				if (current.Key.Equals(query, StringComparison.OrdinalIgnoreCase))
				{
					prefab = current.Value;
					return true;
				}
			}
			prefab = PrefabGUID.Empty;
			return false;
		}

		public static List<ItemMatch> FindItems(string query, int maxResults = 20)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			List<ItemMatch> list = new List<ItemMatch>();
			if (string.IsNullOrWhiteSpace(query) || maxResults < 1)
			{
				return list;
			}
			Enumerator<string, PrefabGUID> enumerator = Core.PrefabCollectionSystem._SpawnableNameToPrefabGuidDictionary.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<string, PrefabGUID> current = enumerator.Current;
				if (current.Key.StartsWith("Item_") && current.Key.Contains(query, StringComparison.OrdinalIgnoreCase))
				{
					list.Add(new ItemMatch(current.Value, current.Key));
				}
			}
			return list.OrderBy<ItemMatch, string>((ItemMatch m) => m.PrefabName, StringComparer.OrdinalIgnoreCase).Take(maxResults).ToList();
		}

		public static string FormatDisplayName(string prefabName)
		{
			if (prefabName.StartsWith("Item_", StringComparison.Ordinal))
			{
				string text = prefabName;
				prefabName = text.Substring(5, text.Length - 5);
			}
			return prefabName.Replace('_', ' ');
		}
	}
	internal sealed class SlotAssignmentService
	{
		private const string ConfigFolderName = "SlotSort";

		private const string DefaultsFileName = "defaults.json";

		private readonly Dictionary<ulong, SlotAssignmentData> playerData = new Dictionary<ulong, SlotAssignmentData>();

		private readonly Dictionary<ulong, int> pendingSlots = new Dictionary<ulong, int>();

		private readonly Dictionary<ulong, (string Query, List<int> ItemGuids)> searchResults = new Dictionary<ulong, (string, List<int>)>();

		private SlotAssignmentData globalDefaults = new SlotAssignmentData();

		private string ConfigRoot => Path.Combine(Paths.ConfigPath, "SlotSort");

		private string DefaultsPath => Path.Combine(ConfigRoot, "defaults.json");

		private string PlayersPath => Path.Combine(ConfigRoot, "players");

		public void LoadDefaults()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			Directory.CreateDirectory(ConfigRoot);
			Directory.CreateDirectory(PlayersPath);
			if (!File.Exists(DefaultsPath))
			{
				globalDefaults = CreateExampleDefaults();
				ResolveMissingGuids(globalDefaults);
				SaveDefaults();
				return;
			}
			try
			{
				string json = File.ReadAllText(DefaultsPath);
				globalDefaults = JsonSerializer.Deserialize<SlotAssignmentData>(json) ?? new SlotAssignmentData();
				ResolveMissingGuids(globalDefaults);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Core.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(30, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to load defaults.json: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				log.LogError(val);
				globalDefaults = new SlotAssignmentData();
			}
		}

		public void LoadAllPlayers()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			playerData.Clear();
			bool flag = default(bool);
			foreach (string item in Directory.EnumerateFiles(PlayersPath, "*.json"))
			{
				if (!ulong.TryParse(Path.GetFileNameWithoutExtension(item), out var result))
				{
					continue;
				}
				try
				{
					SlotAssignmentData slotAssignmentData = JsonSerializer.Deserialize<SlotAssignmentData>(File.ReadAllText(item));
					if (slotAssignmentData != null)
					{
						playerData[result] = slotAssignmentData;
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log = Core.Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(31, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to load player config ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(item);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					log.LogWarning(val);
				}
			}
		}

		public bool IsEnabled(ulong steamId)
		{
			return GetMergedData(steamId).Enabled;
		}

		public bool ToggleEnabled(ulong steamId)
		{
			SlotAssignmentData orCreatePlayerData = GetOrCreatePlayerData(steamId);
			orCreatePlayerData.Enabled = !orCreatePlayerData.Enabled;
			SavePlayer(steamId);
			return orCreatePlayerData.Enabled;
		}

		public IReadOnlyList<SlotAssignmentEntry> GetAssignments(ulong steamId)
		{
			SlotAssignmentData orCreatePlayerData = GetOrCreatePlayerData(steamId);
			HashSet<int> disabled = new HashSet<int>(orCreatePlayerData.DisabledDefaultGuids);
			return MergeAssignments(globalDefaults.Assignments.Where((SlotAssignmentEntry a) => !disabled.Contains(a.ItemGuid)), orCreatePlayerData.Assignments);
		}

		public void SetPendingSlot(ulong steamId, int slot)
		{
			pendingSlots[steamId] = slot;
		}

		public bool TryGetPendingSlot(ulong steamId, out int slot)
		{
			return pendingSlots.TryGetValue(steamId, out slot);
		}

		public void SetSearchResults(ulong steamId, string query, IReadOnlyList<ItemSearchService.ItemMatch> results)
		{
			searchResults[steamId] = (query, results.Select(delegate(ItemSearchService.ItemMatch r)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				PrefabGUID guid = r.Guid;
				return ((PrefabGUID)(ref guid)).GuidHash;
			}).ToList());
		}

		public bool TryGetSearchResults(ulong steamId, out string query, out IReadOnlyList<int> itemGuids)
		{
			if (searchResults.TryGetValue(steamId, out (string, List<int>) value))
			{
				(query, itemGuids) = value;
				return true;
			}
			query = string.Empty;
			itemGuids = Array.Empty<int>();
			return false;
		}

		public bool TrySetAssignment(ulong steamId, PrefabGUID item, int slotNumber, out string error)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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)
			error = string.Empty;
			if (slotNumber < 1)
			{
				error = "Slot number must be at least 1.";
				return false;
			}
			SlotAssignmentData orCreatePlayerData = GetOrCreatePlayerData(steamId);
			orCreatePlayerData.DisabledDefaultGuids.Remove(((PrefabGUID)(ref item)).GuidHash);
			orCreatePlayerData.Assignments.RemoveAll((SlotAssignmentEntry a) => a.ItemGuid == ((PrefabGUID)(ref item)).GuidHash);
			orCreatePlayerData.Assignments.Add(new SlotAssignmentEntry
			{
				ItemGuid = ((PrefabGUID)(ref item)).GuidHash,
				ItemName = item.PrefabName(),
				Slot = slotNumber
			});
			SavePlayer(steamId);
			return true;
		}

		public bool TryRemoveAssignment(ulong steamId, PrefabGUID item, out string error)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			error = string.Empty;
			SlotAssignmentData orCreatePlayerData = GetOrCreatePlayerData(steamId);
			if (orCreatePlayerData.Assignments.RemoveAll((SlotAssignmentEntry a) => a.ItemGuid == ((PrefabGUID)(ref item)).GuidHash) > 0)
			{
				SavePlayer(steamId);
				return true;
			}
			if (globalDefaults.Assignments.Exists((SlotAssignmentEntry a) => a.ItemGuid == ((PrefabGUID)(ref item)).GuidHash) && !orCreatePlayerData.DisabledDefaultGuids.Contains(((PrefabGUID)(ref item)).GuidHash))
			{
				orCreatePlayerData.DisabledDefaultGuids.Add(((PrefabGUID)(ref item)).GuidHash);
				SavePlayer(steamId);
				return true;
			}
			error = "No assignment found for " + item.PrefabName() + ".";
			return false;
		}

		public bool TryRemoveByGuid(ulong steamId, int itemGuid, out string error)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (itemGuid == 0)
			{
				error = "Invalid item id.";
				return false;
			}
			return TryRemoveAssignment(steamId, new PrefabGUID(itemGuid), out error);
		}

		public bool TrySetByGuid(ulong steamId, int itemGuid, int slotNumber, out string error)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (itemGuid == 0)
			{
				error = "Invalid item id.";
				return false;
			}
			return TrySetAssignment(steamId, new PrefabGUID(itemGuid), slotNumber, out error);
		}

		private SlotAssignmentData GetMergedData(ulong steamId)
		{
			SlotAssignmentData orCreatePlayerData = GetOrCreatePlayerData(steamId);
			HashSet<int> disabled = new HashSet<int>(orCreatePlayerData.DisabledDefaultGuids);
			IEnumerable<SlotAssignmentEntry> defaults = globalDefaults.Assignments.Where((SlotAssignmentEntry a) => !disabled.Contains(a.ItemGuid));
			return new SlotAssignmentData
			{
				Enabled = orCreatePlayerData.Enabled,
				Assignments = MergeAssignments(defaults, orCreatePlayerData.Assignments),
				DisabledDefaultGuids = orCreatePlayerData.DisabledDefaultGuids
			};
		}

		private SlotAssignmentData GetOrCreatePlayerData(ulong steamId)
		{
			if (!playerData.TryGetValue(steamId, out var value))
			{
				value = new SlotAssignmentData();
				playerData[steamId] = value;
			}
			return value;
		}

		private static List<SlotAssignmentEntry> MergeAssignments(IEnumerable<SlotAssignmentEntry> defaults, IEnumerable<SlotAssignmentEntry> playerOverrides)
		{
			Dictionary<int, SlotAssignmentEntry> dictionary = new Dictionary<int, SlotAssignmentEntry>();
			foreach (SlotAssignmentEntry @default in defaults)
			{
				dictionary[@default.ItemGuid] = @default;
			}
			foreach (SlotAssignmentEntry playerOverride in playerOverrides)
			{
				dictionary[playerOverride.ItemGuid] = playerOverride;
			}
			return dictionary.Values.OrderBy((SlotAssignmentEntry v) => v.Slot).ToList();
		}

		private void SaveDefaults()
		{
			string contents = JsonSerializer.Serialize(globalDefaults, new JsonSerializerOptions
			{
				WriteIndented = true
			});
			File.WriteAllText(DefaultsPath, contents);
		}

		private void SavePlayer(ulong steamId)
		{
			if (playerData.TryGetValue(steamId, out var value))
			{
				string path = Path.Combine(PlayersPath, $"{steamId}.json");
				string contents = JsonSerializer.Serialize(value, new JsonSerializerOptions
				{
					WriteIndented = true
				});
				File.WriteAllText(path, contents);
			}
		}

		private static void ResolveMissingGuids(SlotAssignmentData data)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (Core.PrefabCollectionSystem == null)
			{
				return;
			}
			foreach (SlotAssignmentEntry assignment in data.Assignments)
			{
				if (assignment.ItemGuid == 0)
				{
					PrefabGUID val = InventorySlotService.ResolveItemGuidByName(assignment.ItemName);
					if (((PrefabGUID)(ref val)).GuidHash != 0)
					{
						assignment.ItemGuid = ((PrefabGUID)(ref val)).GuidHash;
					}
				}
			}
		}

		private static SlotAssignmentData CreateExampleDefaults()
		{
			return new SlotAssignmentData
			{
				Enabled = true,
				Assignments = 
				{
					new SlotAssignmentEntry
					{
						ItemName = "Item_Consumable_BloodRose",
						ItemGuid = 0,
						Slot = 9
					},
					new SlotAssignmentEntry
					{
						ItemName = "Item_Consumable_BloodPotion",
						ItemGuid = 0,
						Slot = 10
					},
					new SlotAssignmentEntry
					{
						ItemName = "Item_Equipment_Cloak",
						ItemGuid = 0,
						Slot = 11
					}
				}
			};
		}
	}
}
namespace SlotSort.Patches
{
	[HarmonyPatch(typeof(SceneSectionStreamingSystem), "ShutdownAsynchrnonousStreamingSupport")]
	internal static class InitializationPatch
	{
		[HarmonyPostfix]
		private static void OneShot_AfterLoad()
		{
			Core.Initialize();
			Plugin.Harmony.Unpatch((MethodBase)typeof(SceneSectionStreamingSystem).GetMethod("ShutdownAsynchrnonousStreamingSupport"), typeof(InitializationPatch).GetMethod("OneShot_AfterLoad"));
		}
	}
	[HarmonyPatch(typeof(SortSingleInventorySystem), "OnUpdate")]
	internal static class SortInventoryPatch
	{
		[HarmonyPostfix]
		private static void AfterSort(SortSingleInventorySystem __instance)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0024: 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_0031: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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 (!Core.HasInitialized)
			{
				return;
			}
			EntityQuery eventQuery = __instance._EventQuery;
			NativeArray<Entity> val = ((EntityQuery)(ref eventQuery)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2));
			try
			{
				Enumerator<Entity> enumerator = val.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Entity current = enumerator.Current;
					if (((Entity)(ref current)).Equals(Entity.Null))
					{
						continue;
					}
					FromCharacter val2 = current.Read<FromCharacter>();
					SortSingleInventoryEvent val3 = current.Read<SortSingleInventoryEvent>();
					InventoryOwner val4 = val2.Character.Read<InventoryOwner>();
					ref NetworkId inventory = ref val3.Inventory;
					object obj = val4;
					if (((object)Unsafe.As<NetworkId, NetworkId>(ref inventory)/*cast due to .constrained prefix*/).Equals(obj))
					{
						ulong platformId = val2.User.Read<User>().PlatformId;
						if (Core.SlotAssignments.IsEnabled(platformId))
						{
							Core.InventorySlots.ApplyAssignments(val2.Character, platformId);
						}
					}
				}
			}
			catch (Exception e)
			{
				Core.LogException(e, "SortInventoryPatch");
			}
			finally
			{
				val.Dispose();
			}
		}
	}
}
namespace SlotSort.Models
{
	internal sealed class SlotAssignmentData
	{
		public bool Enabled { get; set; } = true;

		public List<SlotAssignmentEntry> Assignments { get; set; } = new List<SlotAssignmentEntry>();

		public List<int> DisabledDefaultGuids { get; set; } = new List<int>();
	}
	internal sealed class SlotAssignmentEntry
	{
		public int ItemGuid { get; set; }

		public string ItemName { get; set; } = string.Empty;

		public int Slot { get; set; }
	}
}
namespace SlotSort.Commands
{
	[CommandGroup("slotsort", "ss")]
	internal static class SlotSortCommands
	{
		[Command("gui", null, null, "Open SlotSort settings window (requires ZUI client mod).", null, false)]
		public static void OpenGui(ChatCommandContext ctx)
		{
			//IL_000b: 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)
			Core.Ui.Open(ctx.Event.User, ctx.Event.User.PlatformId);
			ctx.Reply("Opening SlotSort panel. Install <color=yellow>ZUI</color> on your client if the window does not appear.");
		}

		[Command("set", null, null, "Assign an item to a fixed inventory slot (1 = first hotbar slot).", null, false)]
		public static void SetSlot(ChatCommandContext ctx, ItemPrefab item, int slot = -1)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			ulong platformId = ctx.Event.User.PlatformId;
			if (slot < 1 && !Core.SlotAssignments.TryGetPendingSlot(platformId, out slot))
			{
				ctx.Reply("Specify a slot number or pick one in GUI (.slotsort pickslot 12).");
				return;
			}
			if (!Core.SlotAssignments.TrySetAssignment(platformId, item.Prefab, slot, out var error))
			{
				ctx.Reply(error);
				return;
			}
			ctx.Reply($"<color=green>{item.Prefab.PrefabName()}</color> -> slot <color=yellow>{slot}</color>. Press Sort in inventory.");
		}

		[Command("setid", null, null, "Assign item by internal GUID hash (used by GUI).", null, false)]
		public static void SetSlotById(ChatCommandContext ctx, int itemGuid, int slot = -1)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			ulong platformId = ctx.Event.User.PlatformId;
			if (slot < 1 && !Core.SlotAssignments.TryGetPendingSlot(platformId, out slot))
			{
				ctx.Reply("Specify a slot number or pick one first (.slotsort pickslot 12).");
				return;
			}
			if (!Core.SlotAssignments.TrySetByGuid(platformId, itemGuid, slot, out var error))
			{
				ctx.Reply(error);
				return;
			}
			string prefabName = ECSExtensions.PrefabName(new PrefabGUID(itemGuid));
			ctx.Reply($"<color=green>{ItemSearchService.FormatDisplayName(prefabName)}</color> -> slot <color=yellow>{slot}</color>.");
		}

		[Command("search", null, null, "Search items by name and show matches in chat and GUI.", null, false)]
		public static void SearchItems(ChatCommandContext ctx, string query)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			ulong platformId = ctx.Event.User.PlatformId;
			List<ItemSearchService.ItemMatch> list = ItemSearchService.FindItems(query);
			if (list.Count == 0)
			{
				ctx.Reply("No items found matching \"" + query + "\".");
				return;
			}
			Core.SlotAssignments.SetSearchResults(platformId, query, list);
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(44, 2, stringBuilder2);
			handler.AppendLiteral("Found ");
			handler.AppendFormatted(list.Count);
			handler.AppendLiteral(" item(s) for \"<color=yellow>");
			handler.AppendFormatted(query);
			handler.AppendLiteral("</color>\":");
			stringBuilder3.AppendLine(ref handler);
			int num = 0;
			foreach (ItemSearchService.ItemMatch item in list)
			{
				if (num >= 10)
				{
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder4 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(37, 1, stringBuilder2);
					handler.AppendLiteral("  ...and ");
					handler.AppendFormatted(list.Count - 10);
					handler.AppendLiteral(" more in GUI (.slotsort gui)");
					stringBuilder4.AppendLine(ref handler);
					break;
				}
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder5 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(23, 1, stringBuilder2);
				handler.AppendLiteral("  <color=green>");
				handler.AppendFormatted(ItemSearchService.FormatDisplayName(item.PrefabName));
				handler.AppendLiteral("</color>");
				stringBuilder5.AppendLine(ref handler);
				num++;
			}
			ctx.Reply(stringBuilder.ToString().TrimEnd());
			Core.Ui.Open(ctx.Event.User, platformId);
		}

		[Command("pickslot", null, null, "Remember a slot for the next .slotsort set command.", null, false)]
		public static void PickSlot(ChatCommandContext ctx, int slot)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (slot < 1)
			{
				ctx.Reply("Slot must be at least 1.");
				return;
			}
			Core.SlotAssignments.SetPendingSlot(ctx.Event.User.PlatformId, slot);
			ctx.Reply($"Selected slot <color=yellow>{slot}</color>. Now run: .slotsort set \"item name\"");
		}

		[Command("remove", "rm", null, "Remove a slot assignment for an item.", null, false)]
		public static void RemoveSlot(ChatCommandContext ctx, ItemPrefab item)
		{
			//IL_0006: 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)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			ulong platformId = ctx.Event.User.PlatformId;
			if (!Core.SlotAssignments.TryRemoveAssignment(platformId, item.Prefab, out var error))
			{
				ctx.Reply(error);
			}
			else
			{
				ctx.Reply("Removed rule for <color=yellow>" + item.Prefab.PrefabName() + "</color>.");
			}
		}

		[Command("rmid", null, null, "Remove assignment by item GUID (used by GUI).", null, false)]
		public static void RemoveById(ChatCommandContext ctx, int itemGuid)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			ulong platformId = ctx.Event.User.PlatformId;
			if (!Core.SlotAssignments.TryRemoveByGuid(platformId, itemGuid, out var error))
			{
				ctx.Reply(error);
			}
			else
			{
				ctx.Reply("Rule removed.");
			}
		}

		[Command("list", "ls", null, "Show your active slot assignments.", null, false)]
		public static void ListSlots(ChatCommandContext ctx)
		{
			//IL_0006: 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)
			ulong platformId = ctx.Event.User.PlatformId;
			IReadOnlyList<SlotAssignmentEntry> assignments = Core.SlotAssignments.GetAssignments(platformId);
			bool flag = Core.SlotAssignments.IsEnabled(platformId);
			if (assignments.Count == 0)
			{
				ctx.Reply("SlotSort is " + (flag ? "enabled" : "disabled") + ". No assignments configured.");
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(10, 1, stringBuilder2);
			handler.AppendLiteral("SlotSort: ");
			handler.AppendFormatted(flag ? "<color=green>enabled</color>" : "<color=red>disabled</color>");
			stringBuilder3.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(26, 2, stringBuilder2);
			handler.AppendLiteral("Slots 1-");
			handler.AppendFormatted(8);
			handler.AppendLiteral(" = hotbar, ");
			handler.AppendFormatted(9);
			handler.AppendLiteral("+ = bag");
			stringBuilder4.AppendLine(ref handler);
			stringBuilder.AppendLine("Assignments:");
			foreach (SlotAssignmentEntry item in assignments)
			{
				string value = ((item.ItemGuid != 0) ? ECSExtensions.PrefabName(new PrefabGUID(item.ItemGuid)) : item.ItemName);
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder5 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(28, 2, stringBuilder2);
				handler.AppendLiteral("  <color=yellow>");
				handler.AppendFormatted(item.Slot);
				handler.AppendLiteral("</color> -> ");
				handler.AppendFormatted(value);
				stringBuilder5.AppendLine(ref handler);
			}
			ctx.Reply(stringBuilder.ToString().TrimEnd());
		}

		[Command("toggle", null, null, "Enable or disable slot sorting for your character.", null, false)]
		public static void Toggle(ChatCommandContext ctx)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			ulong platformId = ctx.Event.User.PlatformId;
			bool flag = Core.SlotAssignments.ToggleEnabled(platformId);
			ctx.Reply("SlotSort is " + (flag ? "<color=green>enabled</color>" : "<color=red>disabled</color>") + ".");
		}

		[Command("sort", null, null, "Apply slot assignments without pressing the sort button.", null, false)]
		public static void SortNow(ChatCommandContext ctx)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			ulong platformId = ctx.Event.User.PlatformId;
			if (!Core.SlotAssignments.IsEnabled(platformId))
			{
				ctx.Reply("SlotSort is disabled. Use .slotsort toggle");
				return;
			}
			Core.InventorySlots.ApplyAssignments(ctx.Event.SenderCharacterEntity, platformId);
			ctx.Reply("Slot assignments applied.");
		}
	}
}
namespace SlotSort.Commands.Converters
{
	internal readonly record struct ItemPrefab(PrefabGUID Prefab);
	internal sealed class ItemPrefabConverter : CommandArgumentConverter<ItemPrefab>
	{
		public override ItemPrefab Parse(ICommandContext ctx, string input)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (ItemSearchService.TryResolveExact(input, out var prefab))
			{
				return new ItemPrefab(prefab);
			}
			List<ItemSearchService.ItemMatch> list = ItemSearchService.FindItems(input, 2);
			if (list.Count == 1)
			{
				return new ItemPrefab(list[0].Guid);
			}
			if (list.Count > 1)
			{
				throw ctx.Error("Multiple items match \"" + input + "\". Be more specific or use .slotsort search " + input);
			}
			throw ctx.Error("No item found matching \"" + input + "\".");
		}
	}
}