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.4.1
baer1.ChatCommandAPI.dll
Decompiled 2 weeks 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.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("DunGen")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")] [assembly: IgnoresAccessChecksTo("Unity.XR.Management")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("baer1")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) baer1 2025")] [assembly: AssemblyDescription("A Lethal Company modding API for easy creation of Minecraft-style Chat Commands")] [assembly: AssemblyFileVersion("0.4.1.0")] [assembly: AssemblyInformationalVersion("0.4.1+45a5755de4e6f3759a230e50d7ca2bcaf508ef3b")] [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.4.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [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() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } 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) { if (!EqualityComparer<T>.Default.Equals(_item, (T)value)) { return -1; } return 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) { if (!EqualityComparer<T>.Default.Equals(_item, item)) { return -1; } return 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } 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.4.1")] public class ChatCommandAPI : BaseUnityPlugin { internal struct ConfirmationRequest { public string? action; public Action<bool> callback; } internal static ConfirmationRequest? confirmationRequest; internal static Dictionary<ulong, ConfirmationRequest> confirmationRequests = new Dictionary<ulong, ConfirmationRequest>(); internal static ulong? targetClientId; internal ConfigEntry<bool> builtInCommands; private List<ServerCommand> builtInServerCommandList; private List<Command> commandList; private ConfigEntry<string> commandPrefix; private ConfigEntry<bool> enableServerMode; internal List<ServerCommand> serverCommandList; private ConfigEntry<string> serverCommandPrefix; private ConfigEntry<string> serverWelcomeMessage; public static ChatCommandAPI Instance { get; private set; } = null; internal static ManualLogSource Logger { get; private set; } = null; 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 { get { if (!builtInCommands.Value) { return serverCommandList; } return builtInServerCommandList.Concat(serverCommandList).ToList(); } } public string? ServerWelcomeMessage { get { if (!Utility.IsNullOrWhiteSpace(serverWelcomeMessage.Value)) { return string.Format(serverWelcomeMessage.Value.Trim(), ServerCommandPrefix); } return null; } } 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"); 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.4.1 has loaded!"); static void Patch() { //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_0017: 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(); new ServerConfirm(); new ServerDeny(); } 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; if (num <= 1) { if (num == 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(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; if (num <= 1) { if (num == 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(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; } public static void AskConfirm(PlayerControllerB caller, string action, Action<bool> callback) { confirmationRequests[caller.actualClientId] = new ConfirmationRequest { action = action, callback = callback }; } public static void AskConfirm(PlayerControllerB caller, Action<bool> callback) { confirmationRequests[caller.actualClientId] = new ConfirmationRequest { callback = callback }; } public static Task<bool> AskConfirmAsync(PlayerControllerB caller, string action) { TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); confirmationRequests[caller.actualClientId] = new ConfirmationRequest { action = action, callback = taskCompletionSource.SetResult }; return taskCompletionSource.Task; } public static Task<bool> AskConfirmAsync(PlayerControllerB caller) { TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); confirmationRequests[caller.actualClientId] = new ConfirmationRequest { callback = taskCompletionSource.SetResult }; 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_000d: 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_0037: 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(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 { get { if (ToggleDescription != null) { return ToggleDescription + " - " + ValueString; } return 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 { get { if (!Value) { return DisabledString; } return EnabledString; } } 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) { if ((Object)(object)player != (Object)null && player != null && !player.disconnectedMidGame && !player.isTestingPlayer) { if (!player.isPlayerControlled) { return player.isPlayerDead; } return true; } return false; } 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0129: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: 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_0054: 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) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) 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_0043: 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_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0028: 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_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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) if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z)) { return ParsePosition(origin, rotation, x, y, z); } return null; } public static Vector3? ParsePosition(Vector3 origin, string input) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z)) { return ParsePosition(origin, x, y, z); } return null; } public static Vector3? ParsePosition(string input) { if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z)) { return ParsePosition(x, y, z); } return null; } public static bool ParsePosition(Vector3 origin, Quaternion rotation, string input, out Vector3 position) { //IL_0001: 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) position = default(Vector3); if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z)) { return ParsePosition(origin, rotation, x, y, z, out position); } return false; } public static bool ParsePosition(Vector3 origin, string input, out Vector3 position) { //IL_0001: 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) position = default(Vector3); if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z)) { return ParsePosition(origin, x, y, z, out position); } return false; } public static bool ParsePosition(string input, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); if (ParseSingleCommaSeparatedPositionString(input, out string x, out string y, out string z)) { return ParsePosition(x, y, z, out position); } return false; } 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.4.1"; } } namespace ChatCommandAPI.Patches { [HarmonyPatch(typeof(GameNetworkManager), "StartHost")] internal static class GameNetworkManager_StartHost { private static void Postfix() { ServerStatus.startTime = DateTime.Now; ChatCommandAPI.confirmationRequests.Clear(); } } [HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageServerRpc")] internal static class HUDManager_AddPlayerChatMessageServerRpc { private static bool Prefix(ref HUDManager __instance, ref string chatMessage, ref int playerId) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)((NetworkBehaviour)__instance).__rpc_exec_stage != 1 || (!((NetworkBehaviour)__instance).NetworkManager.IsServer && !((NetworkBehaviour)__instance).NetworkManager.IsHost) || Utility.IsNullOrWhiteSpace(chatMessage) || !ChatCommandAPI.Instance.IsServerCommand(chatMessage)) { return true; } ChatCommandAPI.Logger.LogInfo((object)$">> Parsing server command by player {playerId}: {chatMessage}"); PlayerControllerB val = null; if (playerId >= 0 && playerId < StartOfRound.Instance.allPlayerScripts.Length) { val = StartOfRound.Instance.allPlayerScripts[playerId]; } ChatCommandAPI.Logger.LogDebug((object)(" caller: " + (((Object)(object)val == (Object)null) ? "null" : val.playerUsername))); if ((Object)(object)val == (Object)null || !Utils.IsPlayerControlled(val)) { ChatCommandAPI.Logger.LogWarning((object)$"Server command sent by invalid player {playerId}: {chatMessage}"); return true; } if (ChatCommandAPI.Instance.ParseCommand(chatMessage, out string command, out string[] args, out Dictionary<string, string> kwargs)) { StringBuilder stringBuilder = new StringBuilder("<< Parsed command: " + command + "(" + (((Object)(object)val == (Object)null) ? "null" : $"#{val.playerClientId} {val.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, ", ")); ChatCommandAPI.Logger.LogInfo((object)(stringBuilder?.ToString() + ")")); if (!ChatCommandAPI.Instance.RunCommand(val, command, args, kwargs, out string error)) { ChatCommandAPI.Logger.LogWarning((object)(" Error running command: " + (error ?? "null"))); if ((Object)(object)val != (Object)null && error != null) { ChatCommandAPI.PrintCommandError(val, error); } } return false; } ChatCommandAPI.Logger.LogInfo((object)"<< Invalid command"); if ((Object)(object)val != (Object)null) { ChatCommandAPI.PrintError(val, "Invalid command"); } return false; } } [HarmonyPatch(typeof(HUDManager), "AddTextMessageClientRpc")] internal static class HUDManager_AddTextMessageClientRpc { 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(HUDManager_AddTextMessageClientRpc), "RedirectMessageToClient", (Type[])null, (Type[])null) }) .InstructionEnumeration(); } public static ClientRpcParams RedirectMessageToClient(ClientRpcParams clientRpcParams) { //IL_0010: 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_000c: Unknown result type (might be due to invalid IL or missing references) if (!ChatCommandAPI.targetClientId.HasValue) { return clientRpcParams; } ClientRpcParams result = default(ClientRpcParams); result.Send.TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>(ChatCommandAPI.targetClientId.Value); return result; } } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] internal static class HUDManager_SubmitChat_performed { private static bool Prefix(ref HUDManager __instance, ref CallbackContext context) { string text = __instance.chatTextField.text; if (!((CallbackContext)(ref context)).performed || Utility.IsNullOrWhiteSpace(text) || !ChatCommandAPI.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; ChatCommandAPI.Logger.LogInfo((object)(">> Parsing command: " + text)); if (ChatCommandAPI.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, ", ")); ChatCommandAPI.Logger.LogInfo((object)(stringBuilder?.ToString() + ")")); if (!ChatCommandAPI.Instance.RunCommand(command, args, kwargs, out string error)) { ChatCommandAPI.Logger.LogWarning((object)(" Error running command: " + (error ?? "null"))); if (error != null) { ChatCommandAPI.PrintCommandError(error); } } return false; } ChatCommandAPI.Logger.LogInfo((object)"<< Invalid command"); ChatCommandAPI.PrintError("Invalid command"); return false; } } [HarmonyPatch(typeof(StartOfRound), "SyncAlreadyHeldObjectsServerRpc")] internal static class StartOfRound_SyncAlreadyHeldObjectsServerRpc { 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(StartOfRound_SyncAlreadyHeldObjectsServerRpc), "SendWelcomeMessage", (Type[])null, (Type[])null) }).InstructionEnumeration(); } internal static void SendWelcomeMessage(ulong clientId) { if (ChatCommandAPI.Instance.ServerWelcomeMessage != null && !Utility.IsNullOrWhiteSpace(ChatCommandAPI.Instance.ServerWelcomeMessage) && !ChatCommandAPI.Instance.serverCommandList.All((ServerCommand i) => i.Hidden)) { ChatCommandAPI.targetClientId = clientId; HUDManager.Instance.AddTextMessageClientRpc("<color=#7069ff>" + ChatCommandAPI.Instance.ServerWelcomeMessage + "</color>"); ChatCommandAPI.targetClientId = null; } } } } namespace ChatCommandAPI.BuiltinCommands { public class Confirm : Command { public override string[] Commands => new string[3] { Name.ToLower(), "c", "con" }; public override string Description { get { if (ChatCommandAPI.confirmationRequest.HasValue && ChatCommandAPI.confirmationRequest.Value.action != null) { return "Confirms " + ChatCommandAPI.confirmationRequest.Value.action; } return "Confirms an 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 { get { if (ChatCommandAPI.confirmationRequest.HasValue && ChatCommandAPI.confirmationRequest.Value.action != null) { return "Cancels " + ChatCommandAPI.confirmationRequest.Value.action; } return "Cancels an 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_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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: 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 ServerConfirm : ServerCommand { public override string[] Commands => new string[3] { "Confirm".ToLower(), "c", "con" }; public override string Description { get { if (ChatCommandAPI.confirmationRequest.HasValue && ChatCommandAPI.confirmationRequest.Value.action != null) { return "Confirms " + ChatCommandAPI.confirmationRequest.Value.action; } return "Confirms an action"; } } public override bool Hidden => !ChatCommandAPI.confirmationRequest.HasValue; public ServerConfirm() : base(builtIn: true) { } public override bool Invoke(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error) { error = "No action currently needs confirmation"; if (!ChatCommandAPI.confirmationRequests.TryGetValue(caller.actualClientId, out var value)) { return false; } value.callback(obj: true); ChatCommandAPI.confirmationRequests.Remove(caller.actualClientId); return true; } } public class ServerDeny : ServerCommand { public override string[] Commands => new string[3] { "Deny".ToLower(), "d", "den" }; public override string Description { get { if (ChatCommandAPI.confirmationRequest.HasValue && ChatCommandAPI.confirmationRequest.Value.action != null) { return "Cancels " + ChatCommandAPI.confirmationRequest.Value.action; } return "Cancels an action"; } } public override bool Hidden => !ChatCommandAPI.confirmationRequest.HasValue; public ServerDeny() : base(builtIn: true) { } public override bool Invoke(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error) { error = "No action currently needs confirmation"; if (!ChatCommandAPI.confirmationRequests.TryGetValue(caller.actualClientId, out var value)) { return false; } value.callback(obj: false); ChatCommandAPI.confirmationRequests.Remove(caller.actualClientId); 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(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error) { 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(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error) { error = null; 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 { internal 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(PlayerControllerB caller, string[] args, Dictionary<string, string> kwargs, out string? error) { //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) error = null; 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; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }