Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ChatCommandAPI v0.3.1
baer1.ChatCommandAPI.dll
Decompiled 6 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ChatCommandAPI.BuiltinCommands; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Steamworks.Data; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("baer1")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCopyright("Copyright (c) baer1 2025")] [assembly: AssemblyDescription("A Lethal Company modding API for easy creation of Minecraft-style Chat Commands")] [assembly: AssemblyFileVersion("0.3.1.0")] [assembly: AssemblyInformationalVersion("0.3.1+6d8a82c261366b505f2706ac17dc62ddbc423224")] [assembly: AssemblyProduct("ChatCommandsAPI")] [assembly: AssemblyTitle("baer1.ChatCommandAPI")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/baerchen201/LethalChatCommands.git")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 ChatCommandAPI { [BepInPlugin("baer1.ChatCommandAPI", "ChatCommandsAPI", "0.3.1")] public class ChatCommandAPI : BaseUnityPlugin { internal struct ConfirmationRequest { public string? action; public Action<bool> callback; } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] internal class ChatCommandPatch { private static bool Prefix(ref HUDManager __instance, ref CallbackContext context) { string text = __instance.chatTextField.text; if (!((CallbackContext)(ref context)).performed || Utility.IsNullOrWhiteSpace(text) || !Instance.IsCommand(text)) { return true; } __instance.localPlayer.isTypingChat = false; __instance.chatTextField.text = ""; EventSystem.current.SetSelectedGameObject((GameObject)null); __instance.PingHUDElement(__instance.Chat, 2f, 1f, 0.2f); ((Behaviour)__instance.typingIndicator).enabled = false; Logger.LogInfo((object)(">> Parsing command: " + text)); if (Instance.ParseCommand(text, out string command, out string[] args, out Dictionary<string, string> kwargs)) { StringBuilder stringBuilder = new StringBuilder("<< Parsed command: " + command + "("); if (args.Length != 0) { stringBuilder.Append(GeneralExtensions.Join<string>((IEnumerable<string>)args, (Func<string, string>)null, ", ")); if (kwargs.Count > 0) { stringBuilder.Append(", "); } } stringBuilder.Append(GeneralExtensions.Join<string>(kwargs.Select((KeyValuePair<string, string> kvp) => kvp.Key + ": " + kvp.Value), (Func<string, string>)null, ", ")); Logger.LogInfo((object)(stringBuilder?.ToString() + ")")); if (!Instance.RunCommand(command, args, kwargs, out string error)) { Logger.LogWarning((object)(" Error running command: " + (error ?? "null"))); if (error != null) { PrintCommandError(error); } } return false; } Logger.LogInfo((object)"<< Invalid command"); PrintError("Invalid command"); return false; } } [HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageServerRpc")] internal class ServerCommandPatch { protected enum __RpcExecStage { None, Server, Client } private static bool Prefix(ref HUDManager __instance, ref string chatMessage, ref int playerId) { if (Traverse.Create((object)__instance).Field("__rpc_exec_stage").GetValue<__RpcExecStage>() != __RpcExecStage.Server || (!((NetworkBehaviour)__instance).NetworkManager.IsServer && !((NetworkBehaviour)__instance).NetworkManager.IsHost) || Utility.IsNullOrWhiteSpace(chatMessage) || !Instance.IsServerCommand(chatMessage)) { return true; } Logger.LogInfo((object)$">> Parsing server command by player {playerId}: {chatMessage}"); PlayerControllerB caller = null; if (playerId >= 0 && playerId < StartOfRound.Instance.allPlayerScripts.Length) { caller = StartOfRound.Instance.allPlayerScripts[playerId]; } Logger.LogDebug((object)(" caller: " + (((Object)(object)caller == (Object)null) ? "null" : caller.playerUsername))); if ((Object)(object)caller == (Object)null || !Utils.IsPlayerControlled(caller)) { Logger.LogWarning((object)$"Server command sent by invalid player {playerId}: {chatMessage}"); if (!Instance.allowNullCaller.Value) { return true; } } if (Instance.ParseCommand(chatMessage, out string command, out string[] args, out Dictionary<string, string> kwargs)) { StringBuilder stringBuilder = new StringBuilder("<< Parsed command: " + command + "(" + (((Object)(object)caller == (Object)null) ? "null" : $"#{caller.playerClientId} {caller.playerUsername}") + ((args.Length != 0 || kwargs.Count > 0) ? ", " : "")); if (args.Length != 0) { stringBuilder.Append(GeneralExtensions.Join<string>((IEnumerable<string>)args, (Func<string, string>)null, ", ")); if (kwargs.Count > 0) { stringBuilder.Append(", "); } } stringBuilder.Append(GeneralExtensions.Join<string>(kwargs.Select((KeyValuePair<string, string> kvp) => kvp.Key + ": " + kvp.Value), (Func<string, string>)null, ", ")); Logger.LogInfo((object)(stringBuilder?.ToString() + ")")); if (!Instance.RunCommand(ref caller, command, args, kwargs, out string error)) { Logger.LogWarning((object)(" Error running command: " + (error ?? "null"))); if ((Object)(object)caller != (Object)null && error != null) { PrintCommandError(caller, error); } } return false; } Logger.LogInfo((object)"<< Invalid command"); if ((Object)(object)caller != (Object)null) { PrintError(caller, "Invalid command"); } return false; } } [HarmonyPatch(typeof(HUDManager), "AddTextMessageClientRpc")] internal class SendChatPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(NetworkBehaviour), "__endSendClientRpc", (Type[])null, (Type[])null), (string)null) }).Advance(-1).Insert((CodeInstruction[])(object)new CodeInstruction[1] { CodeInstruction.Call(typeof(SendChatPatch), "a", (Type[])null, (Type[])null) }) .InstructionEnumeration(); } public static ClientRpcParams a(ClientRpcParams clientRpcParams) { //IL_0037: 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_0059: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (!targetClientId.HasValue) { return clientRpcParams; } Logger.LogDebug((object)$"Redirecting message to {targetClientId}"); ClientRpcParams result = default(ClientRpcParams); result.Send.TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>(targetClientId.Value); return result; } } [HarmonyPatch(typeof(StartOfRound), "SyncAlreadyHeldObjectsServerRpc")] internal class WelcomePatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0002: 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_0049: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Debug), "Log", new Type[1] { typeof(string) }, (Type[])null), (string)null) }).Insert((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_1, (object)null), CodeInstruction.Call(typeof(WelcomePatch), "a", (Type[])null, (Type[])null) }).InstructionEnumeration(); } internal static void a(ulong clientId) { Logger.LogDebug((object)string.Format(">> WelcomePatch({0}) ServerWelcomeMessage:{1} IsNullOrWhiteSpace:{2} serverCommandList.Count:{3}", clientId, Instance.ServerWelcomeMessage ?? "null", Utility.IsNullOrWhiteSpace(Instance.ServerWelcomeMessage), Instance.serverCommandList.Count)); if (Instance.ServerWelcomeMessage != null && !Utility.IsNullOrWhiteSpace(Instance.ServerWelcomeMessage) && !Instance.serverCommandList.All((ServerCommand i) => i.Hidden)) { targetClientId = clientId; HUDManager.Instance.AddTextMessageClientRpc("<color=#7069ff>" + Instance.ServerWelcomeMessage + "</color>"); targetClientId = null; } } } private ConfigEntry<string> commandPrefix = null; private List<Command> commandList = null; private ConfigEntry<bool> enableServerMode = null; private ConfigEntry<bool> allowNullCaller = null; private ConfigEntry<bool> builtInCommands = null; private ConfigEntry<string> serverCommandPrefix = null; private List<ServerCommand> serverCommandList = null; private List<ServerCommand> builtInServerCommandList = null; private ConfigEntry<string> serverWelcomeMessage = null; internal static ConfirmationRequest? confirmationRequest; internal static ulong? targetClientId; public static ChatCommandAPI Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony? Harmony { get; set; } public string CommandPrefix => commandPrefix.Value; public IReadOnlyList<Command> CommandList => commandList; public bool EnableServerMode => enableServerMode.Value; public string ServerCommandPrefix => serverCommandPrefix.Value; public IReadOnlyList<ServerCommand> ServerCommandList => builtInCommands.Value ? ((IReadOnlyList<ServerCommand>)builtInServerCommandList.Concat(serverCommandList).ToList()) : ((IReadOnlyList<ServerCommand>)serverCommandList); public string? ServerWelcomeMessage => Utility.IsNullOrWhiteSpace(serverWelcomeMessage.Value) ? null : string.Format(serverWelcomeMessage.Value.Trim(), ServerCommandPrefix); private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; commandPrefix = ((BaseUnityPlugin)this).Config.Bind<string>("General", "CommandPrefix", "/", "Client Command Prefix"); enableServerMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "EnableServerMode", true, "Whether to enable server functionality (if you are host, anyone can use commands, even without the mods)"); serverCommandPrefix = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "ServerCommandPrefix", "!", "Sever Command Prefix"); allowNullCaller = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "AllowNullCaller", false, "Whether to allow invalid players to run commands"); builtInCommands = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "BuiltInCommands", true, "Enables 'status' and 'servermods' commands"); serverWelcomeMessage = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "ServerWelcomeMessage", "This server has available commands.\nType {0}help for more information", "A welcome message that is displayed to any player that joins (clear to disable). {0} is replaced with ServerCommandPrefix"); RegisterCommands(); Patch(); Logger.LogInfo((object)"ChatCommandsAPI v0.3.1 has loaded!"); static void Patch() { //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_0018: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("baer1.ChatCommandAPI"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(); Logger.LogDebug((object)"Finished patching!"); } } private void RegisterCommands() { commandList = new List<Command>(); new Help(); new Position(); new PlayerList(); new Confirm(); new Deny(); new ErrorCommand(); serverCommandList = new List<ServerCommand>(); builtInServerCommandList = new List<ServerCommand>(); new ServerHelp(); new ServerStatus(); new ServerMods(); } public bool RegisterCommand(Command command) { Command command2 = command; if (commandList.Any((Command i) => i.GetType() == command2.GetType())) { return false; } commandList.Add(command2); return true; } public bool RegisterServerCommand(ServerCommand command) { ServerCommand command2 = command; if (serverCommandList.Any((ServerCommand i) => i.GetType() == command2.GetType())) { return false; } serverCommandList.Add(command2); return true; } public bool RegisterBuiltInServerCommand(ServerCommand command) { ServerCommand command2 = command; if (builtInServerCommandList.Any((ServerCommand i) => i.GetType() == command2.GetType())) { return false; } builtInServerCommandList.Add(command2); return true; } public bool IsCommand(string command) { return command.StartsWith(CommandPrefix); } public bool IsServerCommand(string command) { return command.StartsWith(ServerCommandPrefix); } public bool ParseCommand(string input, out string command, out string[] args, out Dictionary<string, string> kwargs) { command = null; args = null; kwargs = null; Match match = new Regex("(?:" + Regex.Escape(CommandPrefix) + "|" + Regex.Escape(ServerCommandPrefix) + ")([a-z]+)(?: ([^ =\"]+|(?:\"[^\"]*?\")))*?(?: ([^ =\"]+=[^ \"]+|[^ =\"]+=\"[^\"]*?\"))*\\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline).Match(input); if (!match.Success) { return false; } command = match.Groups[1].Value; List<string> list = new List<string>(); foreach (Capture capture3 in match.Groups[2].Captures) { list.Add(capture3.Value.Replace("\"", "")); } Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (Capture capture4 in match.Groups[3].Captures) { dictionary.Add(capture4.Value.Split('=')[0], capture4.Value.Split('=')[1].Replace("\"", "")); } args = list.ToArray(); kwargs = dictionary; return true; } public bool RunCommand(string command, string[] args, Dictionary<string, string> kwargs, out string? error) { string command2 = command; Command[] array = CommandList.Where((Command i) => i.Commands.Select((string s) => s.ToLower()).Contains(command2.ToLower())).ToArray(); int num = array.Length; int num2 = num; if (num2 <= 1) { if (num2 == 0) { error = "Command " + command2 + " not found"; return false; } } else { Logger.LogWarning((object)("Command " + command2 + " has multiple matches: " + GeneralExtensions.Join<string>(array.Select((Command i) => i.Name + " (" + i.GetType().Assembly.FullName + ")"), (Func<string, string>)null, ", "))); } try { return array[0].Invoke(args, kwargs, out error); } catch (Exception ex) { Logger.LogError((object)ex.ToString()); error = ex.ToString(); return false; } } public bool RunCommand(ref PlayerControllerB? caller, string command, string[] args, Dictionary<string, string> kwargs, out string? error) { string command2 = command; ServerCommand[] array = ServerCommandList.Where((ServerCommand i) => i.Commands.Select((string s) => s.ToLower()).Contains(command2.ToLower())).ToArray(); int num = array.Length; int num2 = num; if (num2 <= 1) { if (num2 == 0) { error = "Command " + command2 + " not found"; return false; } } else { Logger.LogWarning((object)("Server command " + command2 + " has multiple matches: " + GeneralExtensions.Join<string>(array.Select((ServerCommand i) => i.Name + " (" + i.GetType().Assembly.FullName + ")"), (Func<string, string>)null, ", "))); } try { return array[0].Invoke(ref caller, args, kwargs, out error); } catch (Exception ex) { Logger.LogError((object)ex.ToString()); error = ex.ToString(); return false; } } public static void AskConfirm(string action, Action<bool> callback) { ConfirmationRequest value = default(ConfirmationRequest); value.action = action; value.callback = callback; confirmationRequest = value; } public static void AskConfirm(Action<bool> callback) { ConfirmationRequest value = default(ConfirmationRequest); value.callback = callback; confirmationRequest = value; } public static Task<bool> AskConfirmAsync(string action) { TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); ConfirmationRequest value = default(ConfirmationRequest); value.action = action; value.callback = taskCompletionSource.SetResult; confirmationRequest = value; return taskCompletionSource.Task; } public static Task<bool> AskConfirmAsync() { TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); ConfirmationRequest value = default(ConfirmationRequest); value.callback = taskCompletionSource.SetResult; confirmationRequest = value; return taskCompletionSource.Task; } private static void UpdateChat() { ((TMP_Text)HUDManager.Instance.chatText).text = string.Join("\n", HUDManager.Instance.ChatMessageHistory); HUDManager.Instance.PingHUDElement(HUDManager.Instance.Chat, 4f, 1f, 0.2f); } public static void Print(string text) { HUDManager.Instance.ChatMessageHistory.Add("<color=#00ffff>" + text + "</color>"); UpdateChat(); } public static void Print(string text, Color color) { //IL_0018: 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_0042: Unknown result type (might be due to invalid IL or missing references) HUDManager.Instance.ChatMessageHistory.Add($"<color=#{(byte)(color.r * 255f):x2}{(byte)(color.g * 255f):x2}{(byte)(color.b * 255f):x2}>{text}</color>"); UpdateChat(); } [Obsolete] public static void Print(string text, Tuple<byte, byte, byte> color) { HUDManager.Instance.ChatMessageHistory.Add($"<color=#{color.Item1:x2}{color.Item2:x2}{color.Item3:x2}>{text}</color>"); UpdateChat(); } public static void Print(string text, (byte, byte, byte) color) { HUDManager.Instance.ChatMessageHistory.Add($"<color=#{color.Item1:x2}{color.Item2:x2}{color.Item3:x2}>{text}</color>"); UpdateChat(); } public static void Print(string text, byte r, byte g, byte b) { HUDManager.Instance.ChatMessageHistory.Add($"<color=#{r:x2}{g:x2}{b:x2}>{text}</color>"); UpdateChat(); } public static void PrintWarning(string text) { HUDManager.Instance.ChatMessageHistory.Add("<color=#ffff00>" + text + "</color>"); UpdateChat(); } public static void PrintError(string text) { HUDManager.Instance.ChatMessageHistory.Add("<color=#ff0000>" + text + "</color>"); UpdateChat(); } public static void PrintCommandError(string? error) { PrintError("Error running command" + (Utility.IsNullOrWhiteSpace(error) ? "" : (": <noparse>" + error + "</noparse>"))); } public static void Print(PlayerControllerB caller, string text) { SendToPlayer("<color=#00ffff>" + text + "</color>", caller.actualClientId); } public static void Print(PlayerControllerB caller, string text, Color color) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) SendToPlayer($"<color=#{(byte)(color.r * 255f):x2}{(byte)(color.g * 255f):x2}{(byte)(color.b * 255f):x2}>{text}</color>", caller.actualClientId); } [Obsolete] public static void Print(PlayerControllerB caller, string text, Tuple<byte, byte, byte> color) { SendToPlayer($"<color=#{color.Item1:x2}{color.Item2:x2}{color.Item3:x2}>{text}</color>", caller.actualClientId); } public static void Print(PlayerControllerB caller, string text, (byte, byte, byte) color) { SendToPlayer($"<color=#{color.Item1:x2}{color.Item2:x2}{color.Item3:x2}>{text}</color>", caller.actualClientId); } public static void Print(PlayerControllerB caller, string text, byte r, byte g, byte b) { SendToPlayer($"<color=#{r:x2}{g:x2}{b:x2}>{text}</color>", caller.actualClientId); } public static void PrintWarning(PlayerControllerB caller, string text) { SendToPlayer("<color=#ffff00>" + text + "</color>", caller.actualClientId); } public static void PrintError(PlayerControllerB caller, string text) { SendToPlayer("<color=#ff0000>" + text + "</color>", caller.actualClientId); } public static void PrintCommandError(PlayerControllerB caller, string? error) { PrintError(caller, "Error running command" + (Utility.IsNullOrWhiteSpace(error) ? "" : (": <noparse>" + error + "</noparse>"))); } private static void SendToPlayer(string text, ulong clientId) { targetClientId = clientId; HUDManager.Instance.AddTextMessageClientRpc(text); targetClientId = null; } } public abstract class Command { public virtual string Name => GetType().Name; public virtual string[] Commands => new string[1] { Name.ToLower() }; public virtual string? Description => null; public virtual string[]? Syntax => null; public virtual bool Hidden => false; protected Command() { ChatCommandAPI.Instance.RegisterCommand(this); } public abstract bool Invoke(string[] args, Dictionary<string, string> kwargs, out string? error); } public abstract class ServerCommand { public virtual string Name => GetType().Name; public virtual string[] Commands => new string[1] { Name.ToLower() }; public virtual string? Description => null; public virtual string[]? Syntax => null; public virtual bool Hidden => false; protected ServerCommand() { ChatCommandAPI.Instance.RegisterServerCommand(this); } internal ServerCommand(bool builtIn = true) { if (builtIn) { ChatCommandAPI.Instance.RegisterBuiltInServerCommand(this); } else { ChatCommandAPI.Instance.RegisterServerCommand(this); } } public abstract bool Invoke(ref PlayerControllerB? caller, string[] args, Dictionary<string, string> kwargs, out string? error); } public abstract class ToggleCommand : Command { public virtual string? ToggleDescription => null; public sealed override string Description => (ToggleDescription == null) ? ValueString : (ToggleDescription + " - " + ValueString); public sealed override string[] Syntax => new string[2] { "", "{ on | off }" }; public virtual string EnabledString => "enabled"; public virtual string DisabledString => "disabled"; public virtual bool Value { get; set; } public virtual string ValueString => Value ? EnabledString : DisabledString; public virtual void PrintValue() { ChatCommandAPI.Print(Name + " " + ValueString); } public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error) { error = "Invalid argument"; if (args.Length == 0) { Value = !Value; } else { switch (args[0]) { case "on": case "enable": Value = true; break; case "off": case "disable": Value = false; break; default: return false; } } PrintValue(); return true; } } public static class Utils { public static bool IsPlayerControlled(PlayerControllerB? player) { return (Object)(object)player != (Object)null && player != null && !player.disconnectedMidGame && !player.isTestingPlayer && (player.isPlayerControlled || player.isPlayerDead); } public static PlayerControllerB? GetPlayer(string id, out string error, bool strict = false) { string id2 = id; id2 = id2.Trim(); error = "No player specified"; if (id2.Length == 0) { return null; } error = null; string text = id2.ToLower(); if ((text == "@s" || text == "@me") ? true : false) { return GameNetworkManager.Instance.localPlayerController; } uint result; PlayerControllerB[] array; switch (id2[0]) { case '#': if (uint.TryParse(id2.TrimStart('#'), out result) && result < StartOfRound.Instance.allPlayerScripts.Length && IsPlayerControlled(StartOfRound.Instance.allPlayerScripts[result])) { return StartOfRound.Instance.allPlayerScripts[result]; } error = "Invalid player id"; return null; case '@': array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && string.Equals(i.playerUsername, id2.TrimStart('@'), StringComparison.CurrentCultureIgnoreCase)).ToArray(); if (array.Length == 0 && !strict) { array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && i.playerUsername.ToLower().StartsWith(id2.ToLower().TrimStart('@'))).ToArray(); } break; default: if (uint.TryParse(id2, out result) && result < StartOfRound.Instance.allPlayerScripts.Length && IsPlayerControlled(StartOfRound.Instance.allPlayerScripts[result])) { return StartOfRound.Instance.allPlayerScripts[result]; } array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && string.Equals(i.playerUsername, id2, StringComparison.CurrentCultureIgnoreCase)).ToArray(); if (array.Length == 0 && !strict) { array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && i.playerUsername.ToLower().StartsWith(id2.ToLower())).ToArray(); } break; } if (array.Length > 1) { if (strict) { error = "Multiple players match"; return null; } ChatCommandAPI.PrintWarning("Multiple players match, selecting first..."); } if (array.Length != 0) { return array[0]; } error = "No player matches"; return null; } public static bool GetPlayer(string id, out PlayerControllerB player, out string error, bool strict = false) { player = GameNetworkManager.Instance.localPlayerController; PlayerControllerB player2 = GetPlayer(id, out error, strict); if ((Object)(object)player2 == (Object)null) { return false; } player = player2; return true; } public static Vector3? ParsePosition(Vector3 origin, Quaternion rotation, string x, string y, string z) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) x = x.Trim(); y = y.Trim(); z = z.Trim(); ChatCommandAPI.Logger.LogDebug((object)("x:" + x + " y:" + y + ", z:" + z)); if (!x.StartsWith("^") || !y.StartsWith("^") || !z.StartsWith("^")) { return ParsePosition(origin, x, y, z); } string text = x; x = text.Substring(1, text.Length - 1); text = y; y = text.Substring(1, text.Length - 1); text = z; z = text.Substring(1, text.Length - 1); if ((!float.TryParse(x, out var result) && x.Length > 0) || (!float.TryParse(y, out var result2) && y.Length > 0) || (!float.TryParse(z, out var result3) && z.Length > 0)) { return null; } return origin + rotation * Vector3.forward * result3 + rotation * Vector3.up * result2 + rotation * Vector3.right * result; } public static Vector3? ParsePosition(Vector3 origin, string x, string y, string z) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) x = x.Trim(); y = y.Trim(); z = z.Trim(); float result; if (x.StartsWith('~')) { string text = x; x = text.Substring(1, text.Length - 1); if (!float.TryParse(x, out result) && x.Length > 0) { return null; } result += origin.x; } else if (!float.TryParse(x, out result)) { return null; } float result2; if (y.StartsWith('~')) { string text = y; y = text.Substring(1, text.Length - 1); if (!float.TryParse(y, out result2) && y.Length > 0) { return null; } result2 += origin.y; } else if (!float.TryParse(y, out result2)) { return null; } float result3; if (z.StartsWith('~')) { string text = z; z = text.Substring(1, text.Length - 1); if (!float.TryParse(z, out result3) && z.Length > 0) { return null; } result3 += origin.z; } else if (!float.TryParse(z, out result3)) { return null; } return new Vector3(result, result2, result3); } public static Vector3? ParsePosition(string x, string y, string z) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) x = x.Trim(); y = y.Trim(); z = z.Trim(); if (!float.TryParse(x, out var result) || !float.TryParse(y, out var result2) || !float.TryParse(z, out var result3)) { return null; } return new Vector3(result, result2, result3); } public static bool ParsePosition(Vector3 origin, Quaternion rotation, string x, string y, string z, out Vector3 position) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_002b: 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) position = default(Vector3); Vector3? val = ParsePosition(origin, rotation, x, y, z); if (!val.HasValue) { return false; } position = val.Value; return true; } public static bool ParsePosition(Vector3 origin, string x, string y, string z, out Vector3 position) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); Vector3? val = ParsePosition(origin, x, y, z); if (!val.HasValue) { return false; } position = val.Value; return true; } public static bool ParsePosition(string x, string y, string z, out Vector3 position) { //IL_0002: 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) //IL_002b: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); Vector3? val = ParsePosition(x, y, z); if (!val.HasValue) { return false; } position = val.Value; return true; } public static Vector3? ParsePosition(Vector3 origin, Quaternion rotation, string input) { //IL_000e: 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) string x; string y; string z; return (!ParseSingleCommaSeparatedPositionString(input, out x, out y, out z)) ? null : ParsePosition(origin, rotation, x, y, z); } public static Vector3? ParsePosition(Vector3 origin, string input) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) string x; string y; string z; return (!ParseSingleCommaSeparatedPositionString(input, out x, out y, out z)) ? null : ParsePosition(origin, x, y, z); } public static Vector3? ParsePosition(string input) { string x; string y; string z; return (!ParseSingleCommaSeparatedPositionString(input, out x, out y, out z)) ? null : ParsePosition(x, y, z); } public static bool ParsePosition(Vector3 origin, Quaternion rotation, string input, out Vector3 position) { //IL_0002: 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) position = default(Vector3); string x; string y; string z; return ParseSingleCommaSeparatedPositionString(input, out x, out y, out z) && ParsePosition(origin, rotation, x, y, z, out position); } public static bool ParsePosition(Vector3 origin, string input, out Vector3 position) { //IL_0002: 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) position = default(Vector3); string x; string y; string z; return ParseSingleCommaSeparatedPositionString(input, out x, out y, out z) && ParsePosition(origin, x, y, z, out position); } public static bool ParsePosition(string input, out Vector3 position) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); string x; string y; string z; return ParseSingleCommaSeparatedPositionString(input, out x, out y, out z) && ParsePosition(x, y, z, out position); } internal static bool ParseSingleCommaSeparatedPositionString(string input, out string x, out string y, out string z) { x = "0"; y = "0"; z = "0"; Match match = new Regex("^(?:([^,]+),){2}([^,]+)$", RegexOptions.Multiline).Match(input); if (!match.Success) { return false; } x = match.Groups[1].Captures[0].Value; y = match.Groups[1].Captures[1].Value; z = match.Groups[2].Captures[0].Value; return true; } [Obsolete] public static bool IsInsideFactory(Vector3 position) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Object.FindObjectsOfType<OutOfBoundsTrigger>().Any((OutOfBoundsTrigger i) => position.y < ((Component)i).gameObject.transform.position.y); } [Obsolete] public static PlayerControllerB? GetPlayer(string id, bool strict = false) { string id2 = id; id2 = id2.Trim(); string text = id2.ToLower(); if ((text == "@s" || text == "@me") ? true : false) { return GameNetworkManager.Instance.localPlayerController; } uint result; PlayerControllerB[] array; switch (id2[0]) { case '#': if (uint.TryParse(id2.TrimStart('#'), out result) && result < StartOfRound.Instance.allPlayerScripts.Length && IsPlayerControlled(StartOfRound.Instance.allPlayerScripts[result])) { return StartOfRound.Instance.allPlayerScripts[result]; } ChatCommandAPI.PrintError("Invalid player id"); return null; case '@': array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && string.Equals(i.playerUsername, id2.TrimStart('@'), StringComparison.CurrentCultureIgnoreCase)).ToArray(); if (array.Length == 0 && !strict) { array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && i.playerUsername.ToLower().StartsWith(id2.ToLower().TrimStart('@'))).ToArray(); } break; default: if (uint.TryParse(id2, out result) && result < StartOfRound.Instance.allPlayerScripts.Length && IsPlayerControlled(StartOfRound.Instance.allPlayerScripts[result])) { return StartOfRound.Instance.allPlayerScripts[result]; } array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && string.Equals(i.playerUsername, id2, StringComparison.CurrentCultureIgnoreCase)).ToArray(); if (array.Length == 0 && !strict) { array = StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB i) => IsPlayerControlled(i) && i.playerUsername.ToLower().StartsWith(id2.ToLower())).ToArray(); } break; } if (array.Length > 1) { ChatCommandAPI.PrintWarning("Multiple players with this name exist, selecting first..."); } if (array.Length != 0) { return array[0]; } ChatCommandAPI.PrintError("No player with username found"); return null; } [Obsolete] public static bool GetPlayer(string id, out PlayerControllerB player, bool strict = false) { player = GameNetworkManager.Instance.localPlayerController; PlayerControllerB player2 = GetPlayer(id, strict); if ((Object)(object)player2 == (Object)null) { return false; } player = player2; return true; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "baer1.ChatCommandAPI"; public const string PLUGIN_NAME = "ChatCommandsAPI"; public const string PLUGIN_VERSION = "0.3.1"; } } namespace ChatCommandAPI.BuiltinCommands { public class Confirm : Command { public override string[] Commands => new string[3] { Name.ToLower(), "c", "con" }; public override string Description => (!ChatCommandAPI.confirmationRequest.HasValue || ChatCommandAPI.confirmationRequest.Value.action == null) ? "Confirms an action" : ("Confirms " + ChatCommandAPI.confirmationRequest.Value.action); public override bool Hidden => !ChatCommandAPI.confirmationRequest.HasValue; public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error) { error = "No action currently needs confirmation"; if (!ChatCommandAPI.confirmationRequest.HasValue) { return false; } ChatCommandAPI.confirmationRequest.Value.callback(obj: true); ChatCommandAPI.confirmationRequest = null; return true; } } public class Deny : Command { public override string[] Commands => new string[3] { Name.ToLower(), "d", "den" }; public override string Description => (!ChatCommandAPI.confirmationRequest.HasValue || ChatCommandAPI.confirmationRequest.Value.action == null) ? "Cancels an action" : ("Cancels " + ChatCommandAPI.confirmationRequest.Value.action); public override bool Hidden => !ChatCommandAPI.confirmationRequest.HasValue; public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error) { error = "No action currently needs confirmation"; if (!ChatCommandAPI.confirmationRequest.HasValue) { return false; } ChatCommandAPI.confirmationRequest.Value.callback(obj: false); ChatCommandAPI.confirmationRequest = null; return true; } } public class ErrorCommand : Command { public override string Name => "Error"; public override string Description => "Raises a NullReferenceException, for testing"; public override bool Hidden => true; public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error) { error = null; return Func().EndsWith("a"); static string Func() { return null; } } } public class Position : Command { public override string[] Commands => new string[4] { "pos", "getpos", "showpos", Name }; public override string Description => "Shows the current position of [player] or yourself"; public override string[] Syntax => new string[1] { "[player]" }; public override bool Hidden => true; public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) error = null; PlayerControllerB player = GameNetworkManager.Instance.localPlayerController; if (args.Length != 0 && !Utils.GetPlayer(args[0], out player, out error)) { return false; } error = "This player is dead"; if (player.isPlayerDead) { return false; } string[] obj = new string[6] { "Position of player <noparse>", player.playerUsername, ":\n", null, null, null }; Vector3 position = ((Component)player).transform.position; obj[3] = ((object)(Vector3)(ref position)).ToString(); obj[4] = (((Object)(object)((Component)player).transform.parent != (Object)null) ? $"\nrelative to {((Object)((Component)player).transform.parent).name}:\n{((Component)player).transform.parent.InverseTransformPoint(((Component)player).transform.position)}" : ""); obj[5] = "</noparse>"; ChatCommandAPI.Print(string.Concat(obj)); ChatCommandAPI.Logger.LogInfo((object)string.Format("Position of player {0}: {1}{2}", player.playerUsername, ((Component)player).transform.position, ((Object)(object)((Component)player).transform.parent != (Object)null) ? $" - ({((Object)((Component)player).transform.parent).name}){((Component)player).transform.parent.InverseTransformPoint(((Component)player).transform.position)}" : "")); return true; } } public class Help : Command { internal const string SEPARATOR = "<color=#00FFFF>===============</color>\n"; public override bool Hidden => true; public override string Description => "Displays all available commands"; public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error) { error = "No commands have been registered yet"; if (ChatCommandAPI.Instance.CommandList == null || ChatCommandAPI.Instance.CommandList.Count((Command i) => !i.Hidden) == 0) { return false; } ChatCommandAPI.Print("<color=#00FFFF>===============</color>\n" + string.Join("<color=#00FFFF>===============</color>\n", ChatCommandAPI.Instance.CommandList.Where((Command i) => !i.Hidden).Select(delegate(Command i) { StringBuilder stringBuilder = new StringBuilder(i.Name + ((i.Description == null) ? "" : (" - " + i.Description)) + "\n"); string[] array = i.Syntax ?? new string[1]; foreach (string text in array) { stringBuilder.Append("<color=#ffff00>" + ChatCommandAPI.Instance.CommandPrefix + i.Commands[0] + (Utility.IsNullOrWhiteSpace(text) ? "" : " ") + "</color><color=#dddd00><noparse>" + text + "</noparse></color>\n"); } return stringBuilder.ToString(); })) + "<color=#00FFFF>===============</color>\n".Trim()); return true; } } public class PlayerList : Command { public override string[] Commands => new string[2] { "players", Name }; public override string Description => "Lists all active players"; public override bool Hidden => true; public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error) { error = "No players connected"; if (!StartOfRound.Instance.allPlayerScripts.Any(Utils.IsPlayerControlled)) { return false; } ChatCommandAPI.Print("<noparse>" + string.Join('\n', from i in StartOfRound.Instance.allPlayerScripts.Where(Utils.IsPlayerControlled) select $"#{i.playerClientId}: {i.playerUsername}") + "</noparse>"); return true; } } public class ServerHelp : ServerCommand { public override string Name => "Help"; public override bool Hidden => true; public override string Description => "Displays all available commands on the server"; public override bool Invoke(ref PlayerControllerB? caller, string[] args, Dictionary<string, string> kwargs, out string error) { error = "caller is null"; if ((Object)(object)caller == (Object)null) { return false; } error = "This server has no available commands"; if (ChatCommandAPI.Instance.ServerCommandList == null || ChatCommandAPI.Instance.ServerCommandList.Count((ServerCommand i) => !i.Hidden) == 0) { return false; } ChatCommandAPI.Print(caller, "<color=#00FFFF>===============</color>\n" + string.Join("<color=#00FFFF>===============</color>\n", ChatCommandAPI.Instance.ServerCommandList.Where((ServerCommand i) => !i.Hidden).Select(delegate(ServerCommand i) { StringBuilder stringBuilder = new StringBuilder(i.Name + ((i.Description == null) ? "" : (" - " + i.Description)) + "\n"); string[] array = i.Syntax ?? new string[1]; foreach (string text in array) { stringBuilder.Append("<color=#ffff00>" + ChatCommandAPI.Instance.ServerCommandPrefix + i.Commands[0] + (Utility.IsNullOrWhiteSpace(text) ? "" : " ") + "</color><color=#dddd00><noparse>" + text + "</noparse></color>\n"); } return stringBuilder.ToString(); })) + "<color=#00FFFF>===============</color>\n".Trim()); return true; } } public class ServerMods : ServerCommand { public override string Name => "ServerMods"; public override string Description => "Shows a list of all mods installed on the server"; public ServerMods() : base(builtIn: true) { } public override bool Invoke(ref PlayerControllerB? caller, string[] args, Dictionary<string, string> kwargs, out string error) { error = "caller is null"; if ((Object)(object)caller == (Object)null) { return false; } ChatCommandAPI.Print(caller, $"Mods ({Chainloader.PluginInfos.Count}):\n" + GeneralExtensions.Join<string>((IEnumerable<string>)Chainloader.PluginInfos.Select((KeyValuePair<string, PluginInfo> i) => $"{i.Key} ({i.Value.Metadata.Version})").OrderBy<string, string>((string s) => s, StringComparer.CurrentCultureIgnoreCase), (Func<string, string>)null, "\n")); return true; } } public class ServerStatus : ServerCommand { [HarmonyPatch(typeof(GameNetworkManager), "StartHost")] internal class StartPatch { private static void Postfix() { startTime = DateTime.Now; } } private static DateTime startTime = new DateTime(0L); public override string Name => "Status"; public override string Description => "Displays information about this server"; public ServerStatus() : base(builtIn: true) { } public override bool Invoke(ref PlayerControllerB? caller, string[] args, Dictionary<string, string> kwargs, out string error) { //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) error = "caller is null"; if ((Object)(object)caller == (Object)null) { return false; } StringBuilder stringBuilder = new StringBuilder("Current game: "); Lobby? currentLobby = GameNetworkManager.Instance.currentLobby; object obj; if (currentLobby.HasValue) { Lobby value = currentLobby.Value; obj = ((Lobby)(ref value)).GetData("name"); } else { obj = "unknown"; } stringBuilder.Append((string?)obj + "\n"); stringBuilder.Append("Players:\n"); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (Utils.IsPlayerControlled(val)) { stringBuilder.Append(val.isPlayerDead ? "<color=#ff0000>" : ""); stringBuilder.Append($" #{val.playerClientId} {val.playerUsername}"); if (val.isHostPlayerObject) { stringBuilder.Append(" (HOST)"); } stringBuilder.Append(val.isPlayerDead ? "</color>\n" : "\n"); } } if (startTime.Ticks > 0) { TimeSpan timeSpan = DateTime.Now - startTime; stringBuilder.Append($"\nGame time: {(int)timeSpan.TotalHours:D2}:{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}"); } ChatCommandAPI.Print(caller, stringBuilder.ToString()); return true; } } } [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T> { object IEnumerator.Current => _item; T IEnumerator<T>.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { return !_moveNextCalled && (_moveNextCalled = true); } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => 1; T IReadOnlyList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection<T>.Count => 1; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer<T>.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { return (!EqualityComparer<T>.Default.Equals(_item, (T)value)) ? (-1) : 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(_item); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return EqualityComparer<T>.Default.Equals(_item, item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return (!EqualityComparer<T>.Default.Equals(_item, item)) ? (-1) : 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } }