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 + "\".");
}
}
}