Decompiled source of VRoles v1.1.0

VRoles.dll

Decompiled 4 days ago
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<string> list = new List<string>();
			StringBuilder stringBuilder = new StringBuilder();
			string[] array = rawText.Split("\n");
			List<string> list2 = new List<string>();
			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<World> 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<T>(ref T item);

		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 = Core.EntityManager;
				((EntityManager)(ref entityManager)).SetComponentDataRaw(entity, val.TypeIndex, (void*)ptr, num);
			}
		}

		public static void With<T>(this Entity entity, ActionRef<T> 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<T>();
			action(ref item);
			EntityManager entityManager = Core.EntityManager;
			((EntityManager)(ref entityManager)).SetComponentData<T>(entity, item);
		}

		public unsafe static T ReadRW<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 = Core.EntityManager;
			return Marshal.PtrToStructure<T>(new IntPtr(((EntityManager)(ref entityManager)).GetComponentDataRawRW(entity, val.TypeIndex)));
		}

		public 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 = Core.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_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<T>(entity, false);
		}

		public static bool Has<T>(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<T>(), (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<PrefabCollectionSystem>();
			NativeParallelHashMap<PrefabGUID, Entity> 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<T>(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<T>(), (AccessMode)0);
			EntityManager entityManager = Core.EntityManager;
			((EntityManager)(ref entityManager)).AddComponent(entity, val);
		}

		public static void Remove<T>(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<T>(), (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 "<b>" + input + "</b>";
		}

		public static string I(string input)
		{
			return input.Italic();
		}

		public static string Italic(this string input)
		{
			if (Mode != FormatMode.GameChat)
			{
				return input;
			}
			return "<i>" + input + "</i>";
		}

		public static string Underline(this string input)
		{
			if (Mode != FormatMode.GameChat)
			{
				return input;
			}
			return "<u>" + input + "</u>";
		}

		public static string Color(this string input, string color)
		{
			if (Mode != FormatMode.GameChat)
			{
				return input;
			}
			return $"<color={color}>{input}</color>";
		}

		public static string Size(this string input, int size)
		{
			if (Mode != FormatMode.GameChat)
			{
				return input;
			}
			return $"<size={size}>{input}</size>";
		}

		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<string>("VRoles");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" version ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("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<FixedString64Bytes>(val.Event.User.CharacterName);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("(");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<ulong>(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<FixedString64Bytes>(val.Event.User.CharacterName);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("(");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<ulong>(val.Event.User.PlatformId);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") is allowed to use ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(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<string> 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<FixedString64Bytes>(val.Event.User.CharacterName);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("(");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<ulong>(val.Event.User.PlatformId);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") is allowed to use ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(commandName);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" as they have the roles ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(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<FixedString64Bytes>(val.Event.User.CharacterName);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("(");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<ulong>(val.Event.User.PlatformId);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") is not allowed to use ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(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<FixedString64Bytes>(val.Event.User.CharacterName);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("(");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<ulong>(val.Event.User.PlatformId);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") is not allowed to use ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(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<string, HashSet<string>> rolesToCommands = new Dictionary<string, HashSet<string>>(StringComparer.InvariantCultureIgnoreCase);

		private Dictionary<ulong, List<string>> assignedRoles = new Dictionary<ulong, List<string>>();

		private HashSet<string> allowedAdminCommands = new HashSet<string>();

		private HashSet<string> disallowedNonadminCommands = new HashSet<string>();

		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<string> hashSet = new HashSet<string>();
					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<string> 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<string>();
			SaveRole(roleName);
			return true;
		}

		internal bool DeleteRole(string roleName)
		{
			if (!rolesToCommands.Remove(roleName))
			{
				return false;
			}
			foreach (List<string> 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<string> GetRoles()
		{
			return rolesToCommands.Keys;
		}

		public IEnumerable<string> GetPlayersWithRole(string roleName)
		{
			return assignedRoles.Where((KeyValuePair<ulong, List<string>> x) => x.Value.Contains(roleName)).Select(delegate(KeyValuePair<ulong, List<string>> 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<string> GetRoles(ulong platformId)
		{
			if (!assignedRoles.TryGetValue(platformId, out var value))
			{
				return Array.Empty<string>();
			}
			return value;
		}

		public IEnumerable<string> 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<string> GetAllowedAdminCommands()
		{
			return allowedAdminCommands;
		}

		public IEnumerable<string> 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<string>());
			}
			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<string, Entity> playerNameToUserEntityCache = new Dictionary<string, Entity>(StringComparer.InvariantCultureIgnoreCase);

		private Dictionary<ulong, Entity> platformIdToUserEntityCache = new Dictionary<ulong, Entity>();

		private HashSet<string> unboundPlayers = new HashSet<string>(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<User>(), (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<User>();
		}

		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<User>();
		}

		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<Entity> enumerator = ((EntityQuery)(ref userQuery)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).GetEnumerator();
			while (enumerator.MoveNext())
			{
				Entity current = enumerator.Current;
				User val = current.Read<User>();
				if (!(((NetworkedEntity)(ref val.LocalCharacter)).GetEntityOnServer() == Entity.Null))
				{
					FixedString64Bytes name = ((NetworkedEntity)(ref val.LocalCharacter)).GetEntityOnServer().Read<PlayerCharacter>().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<string> 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<RegisteredCommand> 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<FoundCommand>
	{
		public override FoundCommand Parse(ICommandContext ctx, string input)
		{
			string[] tokens = input.Split('.');
			List<RegisteredCommand> 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<FoundCommand> Commands)
	{
		public string Formatted => Name.Group();
	}
	public class FoundGroupConverter : CommandArgumentConverter<FoundGroup>
	{
		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<RegisteredCommand> source = (from c in CommandRegistryQuery.GetAll()
				where c.GroupMatches(inputGroup) && (inputAssembly == null || c.AssemblyMatches(inputAssembly))
				select c).ToList();
			List<string> 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<FoundCommand> 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<FoundRole>
	{
		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<FoundUser>
	{
		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);
		}
	}
}