using System; using System.Collections; 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 BepInEx; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using ProjectM; using ProjectM.Network; using Stunlock.Core; using Unity.Collections; using Unity.Entities; using VCF.Core.Basics; using VRoles.Commands.Converters; using VRoles.Services; using VampireCommandFramework; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("VRoles")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Allows admin commands to be assigned to groups which can be assigned to nonadmins")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0.0+7b1e7987e1163cc3b592c9683c90e5da6e91f345")] [assembly: AssemblyProduct("VRoles")] [assembly: AssemblyTitle("VRoles")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace VRoles { public static class Color { public static string Red = "red"; public static string Primary = "#b0b"; public static string White = "#eee"; public static string LightGrey = "#ccc"; public static string Yellow = "#dd0"; public static string DarkGreen = "#0c0"; public static string Command = "#4ed"; public static string Group = "#b9f"; public static string Orange = "orange"; } internal static class CommandContextExtensions { private const int MAX_MESSAGE_SIZE = 460; internal static void PaginatedReply(this ICommandContext ctx, StringBuilder input) { ctx.PaginatedReply(input.ToString()); } internal static void PaginatedReply(this ICommandContext ctx, string input) { if (input.Length <= 460) { ctx.Reply(input); return; } string[] array = SplitIntoPages(input); for (int i = 0; i < array.Length; i++) { string text = array[i].TrimEnd('\n', '\r', ' '); text = Environment.NewLine + text; ctx.Reply(text); } } internal static string[] SplitIntoPages(string rawText, int pageSize = 460) { List list = new List(); StringBuilder stringBuilder = new StringBuilder(); string[] array = rawText.Split("\n"); List list2 = new List(); string[] array2 = array; foreach (string text in array2) { if (text.Length > pageSize) { string text2 = text; while (!string.IsNullOrWhiteSpace(text2) && text2.Length > pageSize) { int num = text2.LastIndexOf(' ', pageSize - (int)((double)pageSize * 0.05)); if (num <= 0) { num = Math.Min(pageSize - 1, text2.Length); } list2.Add(text2.Substring(0, num)); text2 = text2.Substring(num); } list2.Add(text2); } else { list2.Add(text); } } foreach (string item in list2) { if (stringBuilder.Length + item.Length > pageSize) { list.Add(stringBuilder.ToString()); stringBuilder.Clear(); } stringBuilder.AppendLine(item); } if (stringBuilder.Length > 0) { list.Add(stringBuilder.ToString()); } return list.ToArray(); } } public static class Core { private static World server; private static UserService userService; private static bool _hasInitialized = false; public static World Server => GetServer(); public static EntityManager EntityManager { get; } = Server.EntityManager; public static RoleService RoleService { get; private set; } public static UserService UserService => GetUserService(); public static ManualLogSource Log { get; } = Plugin.LogInstance; private static World GetServer() { if (server == null) { server = GetWorld("Server") ?? throw new Exception("There is no Server world (yet). Did you install a server mod on the client?"); } return server; } private static UserService GetUserService() { if (userService == null) { userService = new UserService(); } return userService; } internal static void InitializeAfterLoaded() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if (!_hasInitialized) { RoleService = new RoleService(); _hasInitialized = true; ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(18, 0, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("VRoles initialized"); } log.LogInfo(val); } } private static World GetWorld(string name) { Enumerator enumerator = World.s_AllWorlds.GetEnumerator(); while (enumerator.MoveNext()) { World current = enumerator.Current; if (current.Name == name) { return current; } } return null; } } public static class ECSExtensions { public delegate void ActionRef(ref T item); public unsafe static void Write(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(), (AccessMode)0); byte[] array = StructureToByteArray(componentData); int num = Marshal.SizeOf(); fixed (byte* ptr = array) { EntityManager entityManager = Core.EntityManager; ((EntityManager)(ref entityManager)).SetComponentDataRaw(entity, val.TypeIndex, (void*)ptr, num); } } public static void With(this Entity entity, ActionRef action) where T : struct { //IL_0000: 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_0014: 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) T item = entity.ReadRW(); action(ref item); EntityManager entityManager = Core.EntityManager; ((EntityManager)(ref entityManager)).SetComponentData(entity, item); } public unsafe static T ReadRW(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(), (AccessMode)0); EntityManager entityManager = Core.EntityManager; return Marshal.PtrToStructure(new IntPtr(((EntityManager)(ref entityManager)).GetComponentDataRawRW(entity, val.TypeIndex))); } public static byte[] StructureToByteArray(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(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(), (AccessMode)0); EntityManager entityManager = Core.EntityManager; return Marshal.PtrToStructure(new IntPtr(((EntityManager)(ref entityManager)).GetComponentDataRawRO(entity, val.TypeIndex))); } public static DynamicBuffer ReadBuffer(this Entity entity) where T : struct { //IL_0005: 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) //IL_000d: 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) EntityManager entityManager = Core.Server.EntityManager; return ((EntityManager)(ref entityManager)).GetBuffer(entity, false); } public static bool Has(this Entity entity) { //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(), (AccessMode)0); EntityManager entityManager = Core.EntityManager; return ((EntityManager)(ref entityManager)).HasComponent(entity, val); } public static string LookupName(this PrefabGUID prefabGuid) { //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_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_0028: 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_0030: Unknown result type (might be due to invalid IL or missing references) PrefabCollectionSystem existingSystemManaged = Core.Server.GetExistingSystemManaged(); NativeParallelHashMap guidToEntityMap = existingSystemManaged._PrefabLookupMap.GuidToEntityMap; if (!guidToEntityMap.ContainsKey(prefabGuid)) { return "GUID Not Found"; } PrefabLookupMap prefabLookupMap = existingSystemManaged._PrefabLookupMap; return ((PrefabLookupMap)(ref prefabLookupMap)).GetName(prefabGuid) + " PrefabGuid(" + ((PrefabGUID)(ref prefabGuid)).GuidHash + ")"; } public static void Add(this Entity entity) { //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(), (AccessMode)0); EntityManager entityManager = Core.EntityManager; ((EntityManager)(ref entityManager)).AddComponent(entity, val); } public static void Remove(this Entity entity) { //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(), (AccessMode)0); EntityManager entityManager = Core.EntityManager; ((EntityManager)(ref entityManager)).RemoveComponent(entity, val); } } public static class Format { public enum FormatMode { GameChat, None } public static FormatMode Mode { get; set; } public static string B(string input) { return input.Bold(); } public static string Bold(this string input) { if (Mode != FormatMode.GameChat) { return input; } return "" + input + ""; } public static string I(string input) { return input.Italic(); } public static string Italic(this string input) { if (Mode != FormatMode.GameChat) { return input; } return "" + input + ""; } public static string Underline(this string input) { if (Mode != FormatMode.GameChat) { return input; } return "" + input + ""; } public static string Color(this string input, string color) { if (Mode != FormatMode.GameChat) { return input; } return $"{input}"; } public static string Size(this string input, int size) { if (Mode != FormatMode.GameChat) { return input; } return $"{input}"; } public static string Small(this string input) { return input.Size(10); } public static string Normal(this string input) { return input.Size(16); } public static string Medium(this string input) { return input.Size(20); } public static string Large(this string input) { return input.Size(24); } public static string Command(this string input) { return input.Bold().Color(VRoles.Color.Command); } public static string Group(this string input) { return input.Bold().Color(VRoles.Color.Group); } public static string Role(this string input) { return input.Bold().Color(VRoles.Color.DarkGreen); } public static string User(this string input) { return input.Bold().Color(VRoles.Color.Orange); } } [BepInPlugin("VRoles", "VRoles", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BasePlugin { private Harmony _harmony; public static Harmony Harmony { get; private set; } public static ManualLogSource LogInstance { get; private set; } public override void Load() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown ManualLogSource log = ((BasePlugin)this).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("VRoles"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" version "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("1.1.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!"); } log.LogInfo(val); LogInstance = ((BasePlugin)this).Log; _harmony = new Harmony("VRoles"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); Harmony = _harmony; CommandRegistry.RegisterAll(); } public override bool Unload() { CommandRegistry.UnregisterAssembly(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } return true; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "VRoles"; public const string PLUGIN_NAME = "VRoles"; public const string PLUGIN_VERSION = "1.1.0"; } } namespace VRoles.Services { public class RoleService { private class RoleMiddleware : CommandMiddleware { private RoleService roleService; public RoleMiddleware(RoleService roleService) { this.roleService = roleService; } public override bool CanExecute(ICommandContext ctx, CommandAttribute command, MethodInfo method) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Expected O, but got Unknown //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) ChatCommandContext val = (ChatCommandContext)ctx; string commandName = GetCommandName(command, method); bool flag = default(bool); if (ctx.IsAdmin) { if (InExecute && command.AdminOnly) { ManualLogSource log = Core.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(32, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.CharacterName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.PlatformId); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") is admin, skipping role check"); } log.LogInfo(val2); } return true; } if (roleService.allowedAdminCommands.Contains(commandName)) { if (InExecute) { ManualLogSource log2 = Core.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(70, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.CharacterName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.PlatformId); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") is allowed to use "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(commandName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" as everyone is allowed to use this admin command"); } log2.LogInfo(val2); } return true; } if (roleService.assignedRoles.TryGetValue(val.User.PlatformId, out var value) && value.Any((string r) => roleService.rolesToCommands[r].Contains(commandName))) { if (InExecute) { IEnumerable values = value.Where((string r) => roleService.rolesToCommands[r].Contains(commandName)); ManualLogSource log3 = Core.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(59, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.CharacterName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.PlatformId); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") is allowed to use "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(commandName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" as they have the roles "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(string.Join(", ", values)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" that allow it"); } log3.LogInfo(val2); } return true; } if (command.AdminOnly) { if (InExecute) { ManualLogSource log4 = Core.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(45, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.CharacterName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.PlatformId); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") is not allowed to use "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(commandName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" as it is admin only"); } log4.LogInfo(val2); } return false; } if (roleService.disallowedNonadminCommands.Contains(commandName)) { if (InExecute) { ManualLogSource log5 = Core.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(59, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.CharacterName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.Event.User.PlatformId); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") is not allowed to use "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(commandName); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" as it is disallowed for nonadmins"); } log5.LogInfo(val2); } return false; } return true; } } private static readonly string CONFIG_PATH = Path.Combine(Paths.ConfigPath, "VRoles"); private static readonly string ROLES_PATH = Path.Combine(CONFIG_PATH, "Roles"); private static readonly string ASSIGNED_ROLES_PATH = Path.Combine(CONFIG_PATH, "user.roles"); private static readonly string ALLOWED_ADMIN_COMMANDS_PATH = Path.Combine(CONFIG_PATH, "allowedAdminCommands.txt"); private static readonly string DISALLOWED_NONADMIN_COMMANDS_PATH = Path.Combine(CONFIG_PATH, "disallowedNonadminCommands.txt"); private Dictionary> rolesToCommands = new Dictionary>(StringComparer.InvariantCultureIgnoreCase); private Dictionary> assignedRoles = new Dictionary>(); private HashSet allowedAdminCommands = new HashSet(); private HashSet disallowedNonadminCommands = new HashSet(); private static bool inExecuteCommandWithArgs = false; private static bool inHelpCmd = false; internal static bool InExecute { get { if (inExecuteCommandWithArgs) { return !inHelpCmd; } return false; } } private static string GetCommandName(CommandAttribute command, MethodInfo method) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown string text = method.DeclaringType.Assembly.GetName().Name; if (method.DeclaringType.IsDefined(typeof(CommandGroupAttribute))) { CommandGroupAttribute val = (CommandGroupAttribute)Attribute.GetCustomAttribute(method.DeclaringType, typeof(CommandGroupAttribute), inherit: false); text = text + "." + val.Name; } return text + "." + command.Name; } internal RoleService() { foreach (CommandMiddleware middleware in CommandRegistry.Middlewares) { if (((object)middleware).GetType() == typeof(BasicAdminCheck)) { CommandRegistry.Middlewares.Remove(middleware); break; } } RoleMiddleware item = new RoleMiddleware(this); CommandRegistry.Middlewares.Add((CommandMiddleware)(object)item); HookUpForSeeingIfCheckingPermission(); LoadSettings(); } private void LoadSettings() { rolesToCommands.Clear(); assignedRoles.Clear(); if (Directory.Exists(ROLES_PATH)) { string[] files = Directory.GetFiles(ROLES_PATH, "*.txt"); foreach (string text in files) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); HashSet hashSet = new HashSet(); rolesToCommands[fileNameWithoutExtension] = hashSet; if (!File.Exists(text)) { continue; } try { string[] array = File.ReadAllLines(text); foreach (string text2 in array) { if (!string.IsNullOrWhiteSpace(text2)) { hashSet.Add(text2.Trim()); } } } catch (Exception ex) { Console.WriteLine("Error loading role file " + text + ": " + ex.Message); } } } if (File.Exists(ASSIGNED_ROLES_PATH)) { try { string[] files = File.ReadAllLines(ASSIGNED_ROLES_PATH); foreach (string text3 in files) { if (string.IsNullOrWhiteSpace(text3)) { continue; } string[] array2 = text3.Split(':', 2); if (array2.Length == 2 && ulong.TryParse(array2[0], out var result)) { List list = (from r in array2[1].Split(',') select r.Trim() into r where !string.IsNullOrWhiteSpace(r) select r).ToList(); if (list.Count > 0) { assignedRoles[result] = list; } } } } catch (Exception ex2) { Console.WriteLine("Error loading role assignments: " + ex2.Message); } } if (File.Exists(ALLOWED_ADMIN_COMMANDS_PATH)) { try { string[] files = File.ReadAllLines(ALLOWED_ADMIN_COMMANDS_PATH); foreach (string text4 in files) { if (!string.IsNullOrWhiteSpace(text4)) { allowedAdminCommands.Add(text4.Trim()); } } } catch (Exception ex3) { Console.WriteLine("Error loading allowed admin commands: " + ex3.Message); } } if (!File.Exists(DISALLOWED_NONADMIN_COMMANDS_PATH)) { return; } try { string[] files = File.ReadAllLines(DISALLOWED_NONADMIN_COMMANDS_PATH); foreach (string text5 in files) { if (!string.IsNullOrWhiteSpace(text5)) { disallowedNonadminCommands.Add(text5.Trim()); } } } catch (Exception ex4) { Console.WriteLine("Error loading disallowed non-admin commands: " + ex4.Message); } } private void SaveRoleAssignments() { if (!Directory.Exists(CONFIG_PATH)) { Directory.CreateDirectory(CONFIG_PATH); } File.WriteAllText(ASSIGNED_ROLES_PATH, string.Join("\n", from x in assignedRoles orderby x.Key select x.Key + ":" + string.Join(", ", x.Value.OrderBy((string r) => r)))); } private void SaveRole(string roleName) { if (!Directory.Exists(ROLES_PATH)) { Directory.CreateDirectory(ROLES_PATH); } File.WriteAllText(Path.Join(ROLES_PATH, roleName + ".txt"), string.Join("\n", rolesToCommands[roleName].OrderBy((string c) => c))); } private void SaveAllowedAdminCommands() { if (!Directory.Exists(CONFIG_PATH)) { Directory.CreateDirectory(CONFIG_PATH); } File.WriteAllText(ALLOWED_ADMIN_COMMANDS_PATH, string.Join("\n", allowedAdminCommands.OrderBy((string c) => c))); } private void SaveDisallowedNonAdminCommands() { if (!Directory.Exists(CONFIG_PATH)) { Directory.CreateDirectory(CONFIG_PATH); } File.WriteAllText(DISALLOWED_NONADMIN_COMMANDS_PATH, string.Join("\n", disallowedNonadminCommands.OrderBy((string c) => c))); } internal string MatchRole(string roleName) { foreach (string key in rolesToCommands.Keys) { if (key.Equals(roleName, StringComparison.InvariantCultureIgnoreCase)) { return key; } } return null; } internal bool CreateRole(string roleName) { if (rolesToCommands.ContainsKey(roleName)) { return false; } rolesToCommands[roleName] = new HashSet(); SaveRole(roleName); return true; } internal bool DeleteRole(string roleName) { if (!rolesToCommands.Remove(roleName)) { return false; } foreach (List value in assignedRoles.Values) { value.Remove(roleName); } string path = Path.Combine(ROLES_PATH, roleName + ".txt"); if (File.Exists(path)) { File.Delete(path); } return true; } public IEnumerable GetRoles() { return rolesToCommands.Keys; } public IEnumerable GetPlayersWithRole(string roleName) { return assignedRoles.Where((KeyValuePair> x) => x.Value.Contains(roleName)).Select(delegate(KeyValuePair> x) { //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) User user = Core.UserService.GetUser(x.Key); return ((FixedString64Bytes)(ref user.CharacterName)).Value; }); } public IEnumerable GetRoles(ulong platformId) { if (!assignedRoles.TryGetValue(platformId, out var value)) { return Array.Empty(); } return value; } public IEnumerable GetCommandsForRole(string roleName) { return rolesToCommands[roleName]; } internal void AllowCommand(FoundCommand command) { if (command.adminOnly) { allowedAdminCommands.Add(command.Name); SaveAllowedAdminCommands(); } else if (disallowedNonadminCommands.Remove(command.Name)) { SaveDisallowedNonAdminCommands(); } } internal void DisallowCommand(FoundCommand command) { if (command.adminOnly) { if (allowedAdminCommands.Remove(command.Name)) { SaveAllowedAdminCommands(); } } else { disallowedNonadminCommands.Add(command.Name); SaveDisallowedNonAdminCommands(); } } public IEnumerable GetAllowedAdminCommands() { return allowedAdminCommands; } public IEnumerable GetDisallowedNonAdminCommands() { return disallowedNonadminCommands; } internal void AssignCommandToRole(string roleName, string commandName) { if (rolesToCommands.TryGetValue(roleName, out var value)) { value.Add(commandName); SaveRole(roleName); } } internal bool RemoveCommandFromRole(string roleName, string commandName) { if (!rolesToCommands.TryGetValue(roleName, out var value)) { return false; } bool num = value.Remove(commandName); if (num) { SaveRole(roleName); } return num; } internal bool AssignRoleToPlatformId(string roleName, ulong platformId) { if (!rolesToCommands.ContainsKey(roleName)) { return false; } if (!assignedRoles.TryGetValue(platformId, out var value)) { value = (assignedRoles[platformId] = new List()); } if (value.Contains(roleName)) { return false; } value.Add(roleName); SaveRoleAssignments(); return true; } internal bool RemoveRoleFromPlatformId(string roleName, ulong platformId) { if (!assignedRoles.TryGetValue(platformId, out var value)) { return false; } bool num = value.Remove(roleName); if (num) { SaveRoleAssignments(); } return num; } private static void EnterExecuteCommandWithArgs() { inExecuteCommandWithArgs = true; } private static void ExitExecuteCommandWithArgs() { inExecuteCommandWithArgs = false; } private static void EnterHelpCommand() { inHelpCmd = true; } private static void ExitHelpCommand() { inHelpCmd = false; } private static void HookUpForSeeingIfCheckingPermission() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(CommandRegistry), "ExecuteCommandWithArgs", (Type[])null, (Type[])null); if (methodInfo == null) { methodInfo = AccessTools.Method(typeof(CommandRegistry), "Handle", (Type[])null, (Type[])null); return; } HarmonyMethod val = new HarmonyMethod(typeof(RoleService), "EnterExecuteCommandWithArgs", (Type[])null); HarmonyMethod val2 = new HarmonyMethod(typeof(RoleService), "ExitExecuteCommandWithArgs", (Type[])null); Plugin.Harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyMethod val3 = new HarmonyMethod(typeof(RoleService), "EnterHelpCommand", (Type[])null); HarmonyMethod val4 = new HarmonyMethod(typeof(RoleService), "ExitHelpCommand", (Type[])null); PropertyInfo property = typeof(CommandRegistry).GetProperty("AssemblyCommandMap", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property == null || !(property.GetValue(null) is IDictionary dictionary)) { return; } foreach (DictionaryEntry item in dictionary) { string text = ((item.Key is Assembly assembly) ? assembly.GetName().Name : (item.Key as string)); if (text == null || !text.StartsWith("VampireCommandFramework", StringComparison.OrdinalIgnoreCase) || !(item.Value is IDictionary dictionary2)) { continue; } foreach (DictionaryEntry item2 in dictionary2) { object key = item2.Key; if (!(item2.Value is IEnumerable enumerable)) { continue; } bool flag = false; { IEnumerator enumerator = enumerable.GetEnumerator(); try { while (enumerator.MoveNext()) { switch (enumerator.Current as string) { case ".help": case ".help-all": flag = true; goto end_IL_01cc; } continue; end_IL_01cc: break; } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } } if (!flag) { continue; } PropertyInfo property2 = key.GetType().GetProperty("Method"); if (!(property2 == null)) { MethodInfo methodInfo2 = property2.GetValue(key) as MethodInfo; if (!(methodInfo2 == null)) { Plugin.Harmony.Patch((MethodBase)methodInfo2, val3, val4, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } } } } public class UserService { private Dictionary playerNameToUserEntityCache = new Dictionary(StringComparer.InvariantCultureIgnoreCase); private Dictionary platformIdToUserEntityCache = new Dictionary(); private HashSet unboundPlayers = new HashSet(StringComparer.InvariantCultureIgnoreCase); private EntityQuery userQuery; public UserService() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) EntityQueryBuilder val = new EntityQueryBuilder(AllocatorHandle.op_Implicit((Allocator)2)); val = ((EntityQueryBuilder)(ref val)).AddAll(new ComponentType(Il2CppType.Of(), (AccessMode)1)); EntityQueryBuilder val2 = ((EntityQueryBuilder)(ref val)).WithOptions((EntityQueryOptions)2); EntityManager entityManager = Core.EntityManager; userQuery = ((EntityManager)(ref entityManager)).CreateEntityQuery(ref val2); ((EntityQueryBuilder)(ref val2)).Dispose(); } internal string UnboundPlayerName(string playerName) { if (!unboundPlayers.TryGetValue(playerName, out var actualValue)) { return null; } return actualValue; } public User GetUser(string playerName) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!playerNameToUserEntityCache.TryGetValue(playerName, out var value)) { RefreshCache(); if (!playerNameToUserEntityCache.TryGetValue(playerName, out value)) { return User.Empty; } } return value.Read(); } public User GetUser(ulong platformId) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!platformIdToUserEntityCache.TryGetValue(platformId, out var value)) { RefreshCache(); if (!platformIdToUserEntityCache.TryGetValue(platformId, out value)) { return User.Empty; } } return value.Read(); } private void RefreshCache() { //IL_001d: 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) //IL_0027: 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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) playerNameToUserEntityCache.Clear(); platformIdToUserEntityCache.Clear(); Enumerator enumerator = ((EntityQuery)(ref userQuery)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).GetEnumerator(); while (enumerator.MoveNext()) { Entity current = enumerator.Current; User val = current.Read(); if (!(((NetworkedEntity)(ref val.LocalCharacter)).GetEntityOnServer() == Entity.Null)) { FixedString64Bytes name = ((NetworkedEntity)(ref val.LocalCharacter)).GetEntityOnServer().Read().Name; if (val.PlatformId == 0L) { unboundPlayers.Add(((FixedString64Bytes)(ref name)).Value); continue; } playerNameToUserEntityCache.Add(((FixedString64Bytes)(ref name)).Value, current); platformIdToUserEntityCache.Add(val.PlatformId, current); } } } } } namespace VRoles.Patches { [HarmonyPatch(typeof(ServerBootstrapSystem), "OnUpdate")] public static class InitializationPatch { [HarmonyPostfix] public static void OneShot_AfterLoad_InitializationPatch() { Core.InitializeAfterLoaded(); Plugin.Harmony.Unpatch((MethodBase)typeof(ServerBootstrapSystem).GetMethod("OnUpdate"), typeof(InitializationPatch).GetMethod("OneShot_AfterLoad_InitializationPatch")); } } } namespace VRoles.Commands { [CommandGroup("role", null)] internal class RoleCommands { [Command("create", "c", null, null, null, true)] public static void CreateRole(ChatCommandContext ctx, string role) { string text = string.Join("_", role.Split(Path.GetInvalidFileNameChars())); if (Core.RoleService.CreateRole(text)) { ctx.Reply("Role " + text.Role() + " created."); } else { ctx.Reply("Role " + text.Role() + " already exists."); } } [Command("delete", "d", null, null, null, true)] public static void DeleteRole(ChatCommandContext ctx, FoundRole role) { if (Core.RoleService.DeleteRole(role.Name)) { ctx.Reply("Role " + role.Formatted + " deleted."); } else { ctx.Reply("Role " + role.Formatted + " does not exist."); } } [Command("list", "l", null, null, null, true)] public static void ListRoles(ChatCommandContext ctx) { ((ICommandContext)(object)ctx).PaginatedReply("Roles:\n" + string.Join("\n", from x in Core.RoleService.GetRoles() orderby x select x.Role() + ": " + string.Join(", ", from u in Core.RoleService.GetPlayersWithRole(x) orderby u select u.User()))); } [Command("list", "l", null, null, null, true)] public static void ListRoles(ChatCommandContext ctx, FoundUser player) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) ctx.Reply("Roles assigned to " + player.Formatted + ": " + string.Join(", ", from r in Core.RoleService.GetRoles(player.User.PlatformId) orderby r select r.Role())); } [Command("mine", "my", null, null, null, false)] public static void ListMyRoles(ChatCommandContext ctx) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) IEnumerable roles = Core.RoleService.GetRoles(ctx.User.PlatformId); if (roles.Any()) { ctx.Reply("Your roles are:" + string.Join(", ", from x in roles orderby x descending select x.Role())); } else { ctx.Reply("You have not been assigned any roles."); } } [Command("listcommands", "lc", null, null, null, false)] public static void ListCommands(ChatCommandContext ctx, FoundRole role = null) { if (role != null) { ((ICommandContext)(object)ctx).PaginatedReply("Commands in the role " + role.Formatted + "\n" + string.Join("\n", from c in Core.RoleService.GetCommandsForRole(role.Name) orderby c select c.Command())); return; } ((ICommandContext)(object)ctx).PaginatedReply("Commands available to everyone:\n" + string.Join("\n", from c in Core.RoleService.GetAllowedAdminCommands() orderby c select c.Command())); ((ICommandContext)(object)ctx).PaginatedReply("Commands disallowed to nonadmins or roles granting it:\n" + string.Join("\n", from c in Core.RoleService.GetDisallowedNonAdminCommands() orderby c select c.Command())); } [Command("add", "a", null, null, null, true)] public static void AssignRole(ChatCommandContext ctx, FoundUser player, FoundRole role) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if (Core.RoleService.AssignRoleToPlatformId(role.Name, player.User.PlatformId)) { ctx.Reply($"Role {role.Formatted} assigned to {player.Formatted}."); if (player.User.PlatformId != ctx.User.PlatformId) { FixedString512Bytes val = default(FixedString512Bytes); ((FixedString512Bytes)(ref val))..ctor("You have been assigned the role " + role.Formatted + "."); ServerChatUtils.SendSystemMessageToClient(Core.EntityManager, player.User, ref val); } } else { ctx.Reply("Player " + player.Formatted + " already has the role " + role.Formatted); } } [Command("remove", "r", null, null, null, true)] public static void RemoveRole(ChatCommandContext ctx, FoundUser player, FoundRole role) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if (Core.RoleService.RemoveRoleFromPlatformId(role.Name, player.User.PlatformId)) { ctx.Reply($"Role {role.Formatted} removed from {player.Formatted}."); if (player.User.PlatformId != ctx.User.PlatformId) { FixedString512Bytes val = default(FixedString512Bytes); ((FixedString512Bytes)(ref val))..ctor("You have had the role " + role.Formatted + " removed."); ServerChatUtils.SendSystemMessageToClient(Core.EntityManager, player.User, ref val); } } else { ctx.Reply("Role " + role.Formatted + " does not exist."); } } [Command("allow", "ac", null, null, null, true)] public static void AddCommandToRole(ChatCommandContext ctx, FoundCommand command, FoundRole role = null) { if (role == null) { Core.RoleService.AllowCommand(command); ctx.Reply("Command " + command.Formatted + " added to everyone."); return; } Core.RoleService.AssignCommandToRole(role.Name, command.Name); ctx.Reply($"Command {command.Formatted} added to role {role.Formatted}."); } [Command("disallow", "dc", null, null, null, true)] public static void RemoveCommandFromRole(ChatCommandContext ctx, FoundCommand command, FoundRole role = null) { if (role == null) { Core.RoleService.DisallowCommand(command); ctx.Reply("Command " + command.Formatted + " removed from everyone who isn't admin or has it via a role."); return; } if (Core.RoleService.RemoveCommandFromRole(role.Name, command.Name)) { ctx.Reply("Removed " + command.Formatted + " from role " + role.Formatted); return; } ctx.Reply($"Command {command.Formatted} not found in role {role.Formatted}."); } [Command("allowgroup", "ag", null, null, null, true)] public static void AllowGroup(ChatCommandContext ctx, FoundGroup group, FoundRole role = null) { foreach (FoundCommand command in group.Commands) { if (role == null) { Core.RoleService.AllowCommand(command); } else { Core.RoleService.AssignCommandToRole(role.Name, command.Name); } } ctx.Reply("Allowed all commands in group " + group.Formatted + ((role != null) ? (" for role " + role.Formatted) : " for everyone") + "."); } [Command("disallowgroup", "dg", null, null, null, true)] public static void DisallowGroup(ChatCommandContext ctx, FoundGroup group, FoundRole role = null) { foreach (FoundCommand command in group.Commands) { if (role == null) { Core.RoleService.DisallowCommand(command); } else { Core.RoleService.RemoveCommandFromRole(role.Name, command.Name); } } ctx.Reply("Disallowed all commands in group " + group.Formatted + ((role != null) ? (" for role " + role.Formatted) : " for everyone") + "."); } } } namespace VRoles.Commands.Converters { internal readonly record struct RegisteredCommand(string Assembly, string Group, string GroupShortHand, string Command, string CommandShortHand, bool AdminOnly) { public bool Grouped => Group != null; public string FullName { get { if (!Grouped) { return Assembly + "." + Command; } return $"{Assembly}.{Group}.{Command}"; } } public string GroupFullName { get { if (!Grouped) { return null; } return Assembly + "." + Group; } } private static bool Eq(string a, string b) { return a?.Equals(b, StringComparison.InvariantCultureIgnoreCase) ?? false; } public bool AssemblyMatches(string token) { return Eq(Assembly, token); } public bool CommandMatches(string token) { if (!Eq(Command, token)) { return Eq(CommandShortHand, token); } return true; } public bool GroupMatches(string token) { if (Grouped) { if (!Eq(Group, token)) { return Eq(GroupShortHand, token); } return true; } return false; } } internal static class CommandRegistryQuery { public static IEnumerable GetAll() { if (!(typeof(CommandRegistry).GetProperty("AssemblyCommandMap", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null) is IDictionary dictionary)) { yield break; } foreach (DictionaryEntry item in dictionary) { string assemblyName = ((item.Key is Assembly assembly) ? assembly.GetName().Name : (item.Key as string)); if (assemblyName == null || !(item.Value is IDictionary dictionary2)) { continue; } foreach (DictionaryEntry item2 in dictionary2) { object key = item2.Key; Type type = key.GetType(); object obj = type.GetProperty("Attribute")?.GetValue(key); if (obj != null) { object obj2 = type.GetProperty("GroupAttribute")?.GetValue(key); Type type2 = obj.GetType(); string command = (string)type2.GetProperty("Name").GetValue(obj); string commandShortHand = (string)type2.GetProperty("ShortHand").GetValue(obj); bool adminOnly = (bool)type2.GetProperty("AdminOnly").GetValue(obj); string text = null; string groupShortHand = null; if (obj2 != null) { Type type3 = obj2.GetType(); text = (string)type3.GetProperty("Name").GetValue(obj2); groupShortHand = (string)type3.GetProperty("ShortHand").GetValue(obj2); } yield return new RegisteredCommand(assemblyName, text, groupShortHand, command, commandShortHand, adminOnly); } } } } } public record FoundCommand(string Name, bool adminOnly) { public string Formatted => Name.Command(); } internal class FoundCommandConverter : CommandArgumentConverter { public override FoundCommand Parse(ICommandContext ctx, string input) { string[] tokens = input.Split('.'); List list = (from c in CommandRegistryQuery.GetAll() where Matches(c, tokens) group c by c.FullName into g select g.First()).ToList(); if (list.Count == 0) { throw ctx.Error("Command " + input.Command() + " not found."); } if (list.Count > 1) { throw ctx.Error("Command " + input.Command() + " is ambiguous. Specify one:\n" + string.Join("\n", list.Select((RegisteredCommand c) => c.FullName))); } RegisteredCommand registeredCommand = list[0]; return new FoundCommand(registeredCommand.FullName, registeredCommand.AdminOnly); } private static bool Matches(RegisteredCommand c, string[] tokens) { return tokens.Length switch { 1 => !c.Grouped && c.CommandMatches(tokens[0]), 2 => (c.GroupMatches(tokens[0]) && c.CommandMatches(tokens[1])) || (!c.Grouped && c.AssemblyMatches(tokens[0]) && c.CommandMatches(tokens[1])), 3 => c.AssemblyMatches(tokens[0]) && c.GroupMatches(tokens[1]) && c.CommandMatches(tokens[2]), _ => false, }; } } public record FoundGroup(string Name, List Commands) { public string Formatted => Name.Group(); } public class FoundGroupConverter : CommandArgumentConverter { public override FoundGroup Parse(ICommandContext ctx, string input) { string[] array = input.Split('.'); string inputAssembly = null; string inputGroup = input; if (array.Length == 2) { inputAssembly = array[0]; inputGroup = array[1]; } List source = (from c in CommandRegistryQuery.GetAll() where c.GroupMatches(inputGroup) && (inputAssembly == null || c.AssemblyMatches(inputAssembly)) select c).ToList(); List list = source.Select((RegisteredCommand c) => c.GroupFullName).Distinct().ToList(); if (list.Count == 0) { throw ctx.Error("No group found with name '" + input + "'."); } if (list.Count > 1) { throw ctx.Error("Group '" + input + "' is ambiguous. Specify one:\n" + string.Join("\n", list)); } string name = list[0]; List commands = source.Select((RegisteredCommand c) => new FoundCommand(c.FullName, c.AdminOnly)).ToList(); return new FoundGroup(name, commands); } } public record FoundRole(string Name) { public string Formatted => Name.Role(); } internal class FoundRoleConverter : CommandArgumentConverter { public override FoundRole Parse(ICommandContext ctx, string input) { return new FoundRole(Core.RoleService.MatchRole(input) ?? throw ctx.Error("Role " + input.Role() + " not found.")); } } public record FoundUser(string Name, User User) { public string Formatted => Name.User(); } internal class FoundUserConverter : CommandArgumentConverter { public override FoundUser Parse(ICommandContext ctx, string input) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) User user = Core.UserService.GetUser(input); if (user == User.Empty) { string text = Core.UserService.UnboundPlayerName(input); if (text == null) { throw ctx.Error("Player " + input.User() + " not found."); } throw ctx.Error("Player " + text.User() + " is unbound."); } return new FoundUser(((FixedString64Bytes)(ref user.CharacterName)).Value, user); } } }