using 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 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.1.5.0")]
[assembly: AssemblyInformationalVersion("0.1.5+74edcbd99be78f87da60b69f579b0c23580a4fff")]
[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.1.5.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.1.5")]
public class ChatCommandAPI : BaseUnityPlugin
{
[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));
PrintError("Error running command: <noparse>" + error + "</noparse>");
}
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));
if ((Object)(object)caller != (Object)null)
{
PrintError(caller, "Error running command: <noparse>" + error + "</noparse>");
}
}
return false;
}
Logger.LogInfo((object)"<< Invalid command");
if ((Object)(object)caller != (Object)null)
{
PrintError(caller, "Invalid command");
}
return false;
}
}
[HarmonyPatch(typeof(HUDManager), "AddTextMessageClientRpc")]
public 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 = default(ClientRpcParams);
clientRpcParams.Send.TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>(targetClientId.Value);
return clientRpcParams;
}
}
[HarmonyPatch(typeof(StartOfRound), "OnClientConnect")]
public 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_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(StartOfRound), "OnPlayerConnectedClientRpc", (Type[])null, (Type[])null), (string)null)
}).Advance(1).Insert((CodeInstruction[])(object)new CodeInstruction[2]
{
new CodeInstruction(OpCodes.Ldarg_1, (object)null),
CodeInstruction.Call(typeof(WelcomePatch), "a", (Type[])null, (Type[])null)
})
.InstructionEnumeration();
}
public static void a(ulong clientId)
{
if (Instance.ServerWelcomeMessage != null && !Utility.IsNullOrWhiteSpace(Instance.ServerWelcomeMessage))
{
targetClientId = clientId;
HUDManager.Instance.AddTextMessageClientRpc("<color=#7069ff>" + Instance.ServerWelcomeMessage.Trim() + "</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 ConfigEntry<string> serverWelcomeMessage = null;
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 => serverCommandList;
public string? ServerWelcomeMessage => Utility.IsNullOrWhiteSpace(serverWelcomeMessage.Value) ? null : serverWelcomeMessage.Value.Trim();
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 'mods' commands");
serverWelcomeMessage = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "ServerWelcomeMessage", "This server has available commands.\nType !help for more information", "A welcome message that is displayed to any player that joins (clear to disable)");
RegisterCommands();
Patch();
Logger.LogInfo((object)"ChatCommandsAPI v0.1.5 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 ErrorCommand();
serverCommandList = new List<ServerCommand>();
new ServerHelp();
if (builtInCommands.Value)
{
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 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;
}
}
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 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);
}
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);
}
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, 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;
}
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 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_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
x = x.Trim();
y = y.Trim();
z = z.Trim();
if (!x.StartsWith("~") || !y.StartsWith("~") || !z.StartsWith("~"))
{
return ParsePosition(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 + 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;
}
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);
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "baer1.ChatCommandAPI";
public const string PLUGIN_NAME = "ChatCommandsAPI";
public const string PLUGIN_VERSION = "0.1.5";
}
}
namespace ChatCommandAPI.BuiltinCommands
{
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_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: 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_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)
error = null;
PlayerControllerB player = GameNetworkManager.Instance.localPlayerController;
if (args.Length != 0 && !Utils.GetPlayer(args[0], out player))
{
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 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 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>" : "");
}
}
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();
}
}