using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using ChatCommands.Attributes;
using ChatCommands.BuiltinCommands;
using ChatCommands.Parsers;
using ComputerysModdingUtilities;
using FishNet;
using FishNet.Connection;
using FishNet.Object;
using HarmonyLib;
using HeathenEngineering.DEMO;
using HeathenEngineering.SteamworksIntegration;
using HeathenEngineering.SteamworksIntegration.UI;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using Unity.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: StraftatMod(true)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ChatCommands")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A library mod for straftat that allows developers to create their own chat commands")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("kestrel.straftat.chatcommands")]
[assembly: AssemblyTitle("ChatCommands")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ChatCommands
{
public static class ChatPatches
{
[HarmonyPatch(typeof(LobbyChatUILogic))]
internal static class LobbyChatUILogicPatch
{
[HarmonyPatch("Start")]
[HarmonyPostfix]
public static void ModifyPanel(GameObject ___theirChatTemplate, Transform ___messageRoot, List<IChatMessage> ___chatMessages, GameObject ___chatPanel, LobbyManager ___lobbyManager)
{
m_lobbyManager = ___lobbyManager;
m_messageTemplate = ___theirChatTemplate;
m_messageRoot = ___messageRoot;
m_chatMessages = ___chatMessages;
}
[HarmonyPatch("OnSendChatMessage")]
[HarmonyPrefix]
public static bool DetectCommand(TMP_InputField ___inputField)
{
string text = ___inputField.text;
if (!text.StartsWith("/"))
{
return true;
}
Evaluator.Evaluate(text.Remove(0, "/".Length));
return false;
}
}
[HarmonyPatch(typeof(MatchChat))]
internal static class MatchChatPatch
{
private static bool m_activeLast = true;
[HarmonyPatch("Update")]
[HarmonyPrefix]
public static void OpenOnCommandPrefix(GameObject ___ChatBox, TMP_InputField ___inputLine)
{
if (Input.GetKeyDown((KeyCode)47) && !___ChatBox.activeSelf)
{
___ChatBox.SetActive(true);
___inputLine.text = "/";
___inputLine.MoveToEndOfLine(false, true);
}
bool activeInHierarchy = ___ChatBox.activeInHierarchy;
if (!activeInHierarchy && m_activeLast)
{
___inputLine.text = string.Empty;
}
m_activeLast = activeInHierarchy;
}
}
public const string c_commandPrefix = "/";
public const KeyCode c_commandHotkey = 47;
private static LobbyManager m_lobbyManager;
private static GameObject m_messageTemplate;
private static Transform m_messageRoot;
private static List<IChatMessage> m_chatMessages;
public static void SendChatMessage(string message)
{
((LobbyData)(ref m_lobbyManager.Lobby)).SendChatMessage(message);
}
public static void ClearChat()
{
foreach (IChatMessage chatMessage in m_chatMessages)
{
try
{
Object.Destroy((Object)(object)chatMessage.GameObject);
}
catch
{
}
}
m_chatMessages.Clear();
}
public static void SendSystemMessage(object message, bool showUsername = true, TextAlignmentOptions alignment = 260)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
GameObject val = Object.Instantiate<GameObject>(m_messageTemplate, m_messageRoot);
val.transform.SetAsLastSibling();
((LayoutGroup)val.GetComponent<VerticalLayoutGroup>()).padding.right = 0;
BasicChatMessage component = val.GetComponent<BasicChatMessage>();
if (component != null)
{
TextMeshProUGUI component2 = ((Component)component.username).GetComponent<TextMeshProUGUI>();
((TMP_Text)component2).alignment = alignment;
TextMeshProUGUI message2 = component.message;
((TMP_Text)message2).alignment = alignment;
((TMP_Text)component2).text = "SYSTEM";
((TMP_Text)message2).text = message.ToString();
if (!showUsername)
{
((Component)component.username).gameObject.SetActive(false);
}
component.IsExpanded = false;
m_chatMessages.Add((IChatMessage)(object)component);
}
else
{
Object.Destroy((Object)(object)val);
Plugin.Logger.LogError((object)$"Failed to send system message \"{message}\" in chat~ null BasicChatMessage.");
}
}
}
[Flags]
public enum CommandFlags
{
None = 0,
HostOnly = 1,
ExplorationOnly = 2,
IngameOnly = 4,
Silent = 8
}
public class Command
{
public readonly MethodInfo method;
public readonly string description;
public readonly CommandFlags flags;
public readonly string name;
public readonly string[] aliases;
public readonly string categoryName;
public readonly ParameterInfo[] parameterInfos;
public readonly int maxParameters;
public readonly int minParameters;
public readonly int registryPriority;
public bool isOverriden;
public Command(MethodInfo method, string name, string description = "no description found", string categoryName = "Misc", CommandFlags flags = CommandFlags.None, int registryPriority = 0, params string[] aliases)
{
this.name = name;
this.aliases = aliases;
this.method = method;
this.description = description;
this.flags = flags;
this.categoryName = categoryName;
this.registryPriority = registryPriority;
parameterInfos = method.GetParameters();
maxParameters = parameterInfos.Length;
minParameters = parameterInfos.Count((ParameterInfo p) => !p.HasDefaultValue);
}
public object Invoke(object[] args)
{
return method.Invoke(null, args);
}
}
public static class CommandRegistry
{
internal static Dictionary<string, Command> Commands { get; private set; } = new Dictionary<string, Command>();
internal static HashSet<string> Categories { get; private set; } = new HashSet<string>();
public static void RegisterCommandsFromAssembly(Assembly assembly)
{
PopulateFromAssembly(assembly);
}
public static void RegisterCommandsFromAssembly()
{
PopulateFromAssembly(Assembly.GetCallingAssembly());
}
public static bool CommandExists(string alias)
{
return Commands.ContainsKey(alias);
}
public static bool CategoryExists(string categoryName)
{
return Categories.Contains(categoryName.ToLower());
}
public static bool TryGet(string alias, out Command command)
{
return Commands.TryGetValue(alias, out command);
}
private static Command[] GetCollisions(Command command)
{
HashSet<Command> hashSet = new HashSet<Command>();
foreach (string item in command.aliases.Append(command.name))
{
if (TryGet(item, out var command2))
{
hashSet.Add(command2);
}
}
return hashSet.ToArray();
}
private static void Add(Command command)
{
Categories.Add(command.categoryName.ToLower());
Commands.Add(command.name, command);
string[] aliases = command.aliases;
foreach (string key in aliases)
{
Commands.Add(key, command);
}
}
private static void AddOverride(Command command)
{
Categories.Add(command.categoryName.ToLower());
Commands[command.name] = command;
string[] aliases = command.aliases;
foreach (string key in aliases)
{
Commands[key] = command;
}
}
internal static void RegisterCommand(Command command)
{
Command[] collisions = GetCollisions(command);
if (collisions.Length == 0)
{
Add(command);
}
else if (collisions.All((Command c) => c.registryPriority < command.registryPriority))
{
Command[] array = collisions;
foreach (Command command2 in array)
{
foreach (string item in command2.aliases.Append(command2.name))
{
Commands.Remove(item);
}
}
command.isOverriden = true;
AddOverride(command);
}
else if (collisions.Any((Command c) => c.registryPriority == command.registryPriority))
{
Assembly definingAssembly = command.method.DeclaringType?.Assembly ?? Assembly.GetCallingAssembly();
LogConflictError(command.aliases.Prepend(command.name).ToArray(), command.registryPriority, definingAssembly);
}
}
private static void PopulateFromAssembly(Assembly assembly)
{
Plugin.Logger.LogInfo((object)("Registering commands from \"" + assembly.GetName().Name + "\""));
foreach (MethodInfo item in from method in assembly.GetTypes().SelectMany((Type type) => type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
where method.IsDefined(typeof(CommandAttribute), inherit: false)
select method)
{
Type declaringType = item.DeclaringType;
CommandAttribute customAttribute = item.GetCustomAttribute<CommandAttribute>();
bool flag = item.IsDefined(typeof(CommandAliasesAttribute), inherit: false);
bool num = item.IsDefined(typeof(CommandOverrideAttribute), inherit: false);
string categoryName = (((object)declaringType == null || !declaringType.IsDefined(typeof(CommandCategoryAttribute), inherit: false)) ? "Misc" : declaringType.GetCustomAttribute<CommandCategoryAttribute>()?.name);
int registryPriority = (num ? item.GetCustomAttribute<CommandOverrideAttribute>().priority : 0);
Command command;
if (flag)
{
CommandAliasesAttribute customAttribute2 = item.GetCustomAttribute<CommandAliasesAttribute>();
command = new Command(item, customAttribute.name, customAttribute.description, categoryName, customAttribute.flags, registryPriority, customAttribute2.aliases);
}
else
{
command = new Command(item, customAttribute.name, customAttribute.description, categoryName, customAttribute.flags, registryPriority);
}
RegisterCommand(command);
}
}
private static void LogConflictError(string[] problematicCommandNames, int priorityAttempted, Assembly definingAssembly)
{
Plugin.Logger.LogError((object)($"Error when registering command \"{problematicCommandNames[0]}\" from \"{definingAssembly.GetName().Name}\" w/ priority {priorityAttempted}:" + " a command with the same name or one of the same aliases is already registered with the same priority!"));
Plugin.Logger.LogError((object)"Command conflicts:");
for (int i = 0; i < problematicCommandNames.Length; i++)
{
if (!TryGet(problematicCommandNames[i], out var command))
{
continue;
}
StringBuilder stringBuilder = new StringBuilder("\"" + (command.method.DeclaringType?.Assembly.GetName().Name ?? "UNKNOWN ASSEMBLY") + "\" registers [");
stringBuilder.Append("\"").Append(command.name).Append("\" w/ priority: ")
.Append(command.registryPriority);
if (command.aliases.Length != 0)
{
stringBuilder.Append(", aliases: ");
string[] aliases = command.aliases;
foreach (string value in aliases)
{
stringBuilder.Append("\"").Append(value).Append("\" ");
}
}
stringBuilder.Append("\b]");
Plugin.Logger.LogWarning((object)stringBuilder.ToString());
stringBuilder.Clear();
}
}
[Obsolete("slow. bad idea.")]
internal static void PopulateAll()
{
foreach (Assembly item in from plugin in Chainloader.PluginInfos.Values
select (plugin == null) ? null : ((object)plugin.Instance)?.GetType().Assembly into assembly
where (object)assembly != null
select assembly)
{
PopulateFromAssembly(item);
}
}
}
public static class Evaluator
{
public static void Evaluate(string input)
{
Queue<CommandLexer.Token> tokens = new CommandLexer(input).GetTokens();
List<string> list = new List<string>();
object obj = null;
while (tokens.Count > 0)
{
CommandLexer.Token token = tokens.Dequeue();
switch (token.type)
{
case CommandLexer.TokenType.Seperator:
if (list.Count != 0)
{
string name2 = list[0];
list.RemoveAt(0);
if (obj != null)
{
list.Add(obj.ToString());
obj = null;
}
RunCommand(name2, list.ToArray());
list.Clear();
}
break;
case CommandLexer.TokenType.Pipe:
if (list.Count != 0)
{
string name = list[0];
list.RemoveAt(0);
if (obj != null)
{
list.Add(obj.ToString());
}
obj = RunCommand(name, list.ToArray(), sendResult: false);
list.Clear();
}
break;
default:
list.Add(token.content);
break;
}
}
}
public static object RunCommand(string name, string[] args, bool sendResult = true)
{
if (!CommandRegistry.TryGet(name, out var command))
{
SystemMessage("No command found with name \"" + name + "\".");
return null;
}
if (command.flags.HasFlag(CommandFlags.IngameOnly) && Settings.Instance.inMenu)
{
SystemMessage("The command \"" + name + "\" can only be run while in a game!");
return null;
}
if (command.flags.HasFlag(CommandFlags.HostOnly) && !InstanceFinder.IsHost)
{
SystemMessage("The command \"" + name + "\" can only be run as a lobby host!");
}
if (command.flags.HasFlag(CommandFlags.ExplorationOnly) && !SceneMotor.Instance.testMap)
{
SystemMessage("The command \"" + name + "\" can only be run in exploration mode!");
return null;
}
int num = args.Length;
if (num < command.minParameters)
{
SystemMessage(string.Format("Mismatched parameter counts: command \"{0}\" expects at least {1}, but {2} {3} provided.", name, command.minParameters, num, (num == 1) ? "was" : "were"));
return null;
}
if (num > command.maxParameters)
{
SystemMessage(string.Format("Mismatched parameter counts: command \"{0}\" expects at most {1}, but {2} {3} provided.", name, command.maxParameters, num, (num == 1) ? "was" : "were"));
return null;
}
object[] array = new object[command.maxParameters];
for (int i = 0; i < num; i++)
{
Type parameterType = command.parameterInfos[i].ParameterType;
try
{
array[i] = ParserLocator.ParseTo(parameterType, args[i]);
}
catch
{
SystemMessage("Invalid parameter: command \"" + name + "\" expects the parameter \"" + command.parameterInfos[i].Name + "\" to be of type " + parameterType.Name + ", but the provided parameter (\"" + args[i] + "\") could not be converted to it!");
return null;
}
}
if (command.maxParameters > num)
{
for (int j = num; j < command.maxParameters; j++)
{
array[j] = command.parameterInfos[j].DefaultValue;
}
}
try
{
object obj2 = command.Invoke(array);
if (obj2 != null && !command.flags.HasFlag(CommandFlags.Silent) && sendResult)
{
SystemMessage(obj2);
}
return obj2;
}
catch (Exception ex)
{
Exception innerMostException = ex.GetInnerMostException();
if (innerMostException is CommandException ex2)
{
SystemMessage("Command \"" + name + "\" failed: " + ex2.Message);
}
else
{
SystemMessage($"Unknown error running command \"{name}\": {innerMostException}");
}
return null;
}
}
private static void SystemMessage(object msg)
{
ChatPatches.SendSystemMessage(msg, showUsername: true, (TextAlignmentOptions)260);
}
}
internal class CommandLexer
{
public enum TokenType
{
Identifier,
NestedString,
Seperator,
Pipe
}
public readonly struct Token
{
public readonly string content;
public readonly TokenType type;
public static Token Seperator => new Token(";", TokenType.Seperator);
public static Token Pipe => new Token("|", TokenType.Pipe);
public Token(string content, TokenType type)
{
this.content = content;
this.type = type;
}
}
[CompilerGenerated]
private string <source>P;
private int m_pos;
private StringBuilder m_builder;
public CommandLexer(string source)
{
<source>P = source;
m_builder = new StringBuilder();
base..ctor();
}
private static bool IsSeperator(char c)
{
if (c == '\n' || c == ';')
{
return true;
}
return false;
}
private static bool IsPipe(char c)
{
if (c == '>' || c == '|')
{
return true;
}
return false;
}
private static bool IsQuote(char c)
{
if (c == '"' || c == '\'')
{
return true;
}
return false;
}
private static bool IsIdentifierChar(char c)
{
bool flag = char.IsLetterOrDigit(c);
if (!flag)
{
bool flag2;
switch (c)
{
case '(':
case ')':
case ',':
case '-':
case '.':
case ':':
case '_':
flag2 = true;
break;
default:
flag2 = false;
break;
}
flag = flag2;
}
return flag;
}
private static bool IsIgnorable(char c)
{
if (!IsSeperator(c) && !IsQuote(c) && !IsIdentifierChar(c))
{
return !IsPipe(c);
}
return false;
}
private static char GetEscaped(char c)
{
return c switch
{
'n' => '\n',
'r' => '\r',
't' => '\t',
'b' => '\b',
_ => c,
};
}
private void SkipIgnorables()
{
while (m_pos < <source>P.Length && IsIgnorable(<source>P[m_pos]))
{
m_pos++;
}
}
private bool TryGetNextToken(out Token token)
{
SkipIgnorables();
token = default(Token);
if (m_pos == <source>P.Length)
{
return false;
}
TokenType tokenType = TokenType.Identifier;
char c = '\0';
char c2 = <source>P[m_pos];
if (IsQuote(c2))
{
tokenType = TokenType.NestedString;
c = c2;
m_pos++;
}
else
{
if (IsSeperator(c2))
{
m_pos++;
token = Token.Seperator;
return true;
}
if (IsPipe(c2))
{
m_pos++;
token = Token.Pipe;
return true;
}
}
while (m_pos < <source>P.Length)
{
char c3 = <source>P[m_pos];
if (tokenType == TokenType.Identifier)
{
if (!IsIdentifierChar(c3))
{
break;
}
}
else if (c3 == '\\' && m_pos + 1 < <source>P.Length)
{
c3 = GetEscaped(<source>P[++m_pos]);
}
else if (c3 == c)
{
m_pos++;
break;
}
m_builder.Append(c3);
m_pos++;
}
string content = m_builder.ToString();
token = new Token(content, tokenType);
m_builder.Clear();
return true;
}
public Queue<Token> GetTokens()
{
Queue<Token> queue = new Queue<Token>();
Token token;
while (TryGetNextToken(out token))
{
queue.Enqueue(token);
}
queue.Enqueue(Token.Seperator);
return queue;
}
}
public class CommandException : Exception
{
public CommandException()
{
}
public CommandException(string message)
: base(message)
{
}
public CommandException(string message, Exception inner)
: base(message, inner)
{
}
}
[BepInPlugin("kestrel.straftat.chatcommands", "ChatCommands", "1.0.2")]
internal class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Logger;
public static readonly string loadBearingColonThree = ":3";
public static Plugin Instance { get; private set; }
private void Awake()
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
if (loadBearingColonThree != ":3")
{
Application.Quit();
}
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
WeaponLoader.Init();
BindingCommands.Init();
AdminCommands.Init();
CommandRegistry.RegisterCommandsFromAssembly();
new Harmony("kestrel.straftat.chatcommands").PatchAll();
Logger.LogInfo((object)"Hiiiiiiiiiiii :3");
}
private void Update()
{
BindingCommands.Update();
}
}
internal static class ExceptionExtensions
{
public static Exception GetInnerMostException(this Exception ex)
{
while (ex.InnerException != null && ex != null)
{
ex = ex.InnerException;
}
return ex;
}
}
internal static class Utils
{
public static IEnumerable<TValue> RandomValues<TKey, TValue>(IDictionary<TKey, TValue> dict)
{
List<TValue> values = dict.Values.ToList();
int size = dict.Count;
while (true)
{
yield return values[Random.Range(0, size - 1)];
}
}
public static bool AnyInputFieldFocused()
{
GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
if (!Object.op_Implicit((Object)(object)currentSelectedGameObject))
{
return false;
}
TMP_InputField component = currentSelectedGameObject.GetComponent<TMP_InputField>();
if (component != null)
{
return component.isFocused;
}
return false;
}
public static T LoadFromJsonFile<T>(string path)
{
if (!File.Exists(path))
{
return default(T);
}
return JsonConvert.DeserializeObject<T>(File.ReadAllText(path));
}
public static void SaveToJsonFile<T>(T obj, string path)
{
File.WriteAllText(path, JsonConvert.SerializeObject((object)obj, (Formatting)1));
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "kestrel.straftat.chatcommands";
public const string PLUGIN_NAME = "ChatCommands";
public const string PLUGIN_VERSION = "1.0.2";
}
}
namespace ChatCommands.Parsers
{
internal class BoolParser : ParserBase
{
public override Type ParseResultType => typeof(bool);
public override object Parse(string value)
{
if (bool.TryParse(value, out var result))
{
return result;
}
if (int.TryParse(value, out var result2))
{
return result2 > 0;
}
throw new InvalidCastException();
}
}
internal class KeyCodeParser : ParserBase
{
private static Dictionary<string, KeyCode> m_alternativeStrings = new Dictionary<string, KeyCode>
{
{
"1",
(KeyCode)257
},
{
"2",
(KeyCode)258
},
{
"3",
(KeyCode)259
},
{
"4",
(KeyCode)260
},
{
"5",
(KeyCode)261
},
{
"6",
(KeyCode)262
},
{
"7",
(KeyCode)263
},
{
"8",
(KeyCode)264
},
{
"9",
(KeyCode)265
},
{
"0",
(KeyCode)256
},
{
"!",
(KeyCode)33
},
{
"\"",
(KeyCode)34
},
{
"#",
(KeyCode)35
},
{
"$",
(KeyCode)36
},
{
"&",
(KeyCode)38
},
{
"'",
(KeyCode)39
},
{
"(",
(KeyCode)40
},
{
")",
(KeyCode)41
},
{
"*",
(KeyCode)42
},
{
"+",
(KeyCode)43
},
{
",",
(KeyCode)44
},
{
"-",
(KeyCode)45
},
{
".",
(KeyCode)46
},
{
"/",
(KeyCode)47
},
{
":",
(KeyCode)58
},
{
";",
(KeyCode)59
},
{
"<",
(KeyCode)60
},
{
"=",
(KeyCode)61
},
{
">",
(KeyCode)62
},
{
"?",
(KeyCode)63
},
{
"@",
(KeyCode)64
},
{
"[",
(KeyCode)91
},
{
"\\",
(KeyCode)92
},
{
"]",
(KeyCode)93
},
{
"^",
(KeyCode)94
},
{
"_",
(KeyCode)95
},
{
"`",
(KeyCode)96
},
{
"shift",
(KeyCode)304
},
{
"rshift",
(KeyCode)303
},
{
"ctrl",
(KeyCode)306
},
{
"rctrl",
(KeyCode)305
},
{
"alt",
(KeyCode)308
},
{
"ralt",
(KeyCode)307
},
{
"enter",
(KeyCode)13
},
{
"lwin",
(KeyCode)311
},
{
"rwin",
(KeyCode)312
},
{
"apps",
(KeyCode)319
},
{
"ins",
(KeyCode)277
},
{
"del",
(KeyCode)127
},
{
"pgdn",
(KeyCode)281
},
{
"pgup",
(KeyCode)280
},
{
"kp_end",
(KeyCode)257
},
{
"kp_downarrow",
(KeyCode)258
},
{
"kp_pgdn",
(KeyCode)259
},
{
"kp_leftarrow",
(KeyCode)260
},
{
"kp_5",
(KeyCode)261
},
{
"kp_rightarrow",
(KeyCode)262
},
{
"kp_home",
(KeyCode)263
},
{
"kp_uparrow",
(KeyCode)264
},
{
"kp_pgup",
(KeyCode)265
},
{
"kp_enter",
(KeyCode)271
},
{
"kp_ins",
(KeyCode)256
},
{
"kp_del",
(KeyCode)266
},
{
"kp_slash",
(KeyCode)267
},
{
"kp_multiply",
(KeyCode)268
},
{
"kp_minus",
(KeyCode)269
},
{
"kp_plus",
(KeyCode)270
}
};
public override Type ParseResultType => typeof(KeyCode);
public override object Parse(string value)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
if (m_alternativeStrings.TryGetValue(value.ToLower(), out var value2))
{
return value2;
}
if (Enum.TryParse(typeof(KeyCode), value, ignoreCase: true, out object result))
{
return result;
}
throw new InvalidCastException();
}
}
public abstract class ParserBase
{
public abstract Type ParseResultType { get; }
public abstract object Parse(string value);
}
public static class ParserLocator
{
private static Dictionary<Type, ParserBase> m_parsers;
static ParserLocator()
{
m_parsers = new Dictionary<Type, ParserBase>();
foreach (Type item in from t in Assembly.GetExecutingAssembly().GetTypes()
where t.IsSubclassOf(typeof(ParserBase)) && !t.IsAbstract
select t)
{
ParserBase parserBase = Activator.CreateInstance(item) as ParserBase;
m_parsers.TryAdd(parserBase.ParseResultType, parserBase);
}
}
public static void RegisterParsersFromAssembly()
{
RegisterParsersFromAssembly(Assembly.GetCallingAssembly());
}
public static void RegisterParsersFromAssembly(Assembly assembly)
{
foreach (Type item in from t in assembly.GetTypes()
where t.IsSubclassOf(typeof(ParserBase)) && !t.IsAbstract
select t)
{
ParserBase parserBase = Activator.CreateInstance(item) as ParserBase;
m_parsers.TryAdd(parserBase.ParseResultType, parserBase);
}
}
private static bool TryIConvertible(Type resultType, string input, out object result)
{
result = null;
if (!typeof(IConvertible).IsAssignableFrom(resultType) || m_parsers.ContainsKey(resultType))
{
return false;
}
result = Convert.ChangeType(input, resultType);
return true;
}
public static object ParseTo(Type type, string input)
{
if (TryIConvertible(type, input, out var result))
{
return result;
}
if (m_parsers.TryGetValue(type, out var value))
{
return value.Parse(input);
}
throw new NotSupportedException("Type not supported.");
}
public static bool TryParseTo(Type type, string input, out object result)
{
if (TryIConvertible(type, input, out result))
{
return true;
}
if (!m_parsers.TryGetValue(type, out var value))
{
return false;
}
try
{
result = value.Parse(input);
}
catch
{
return false;
}
return true;
}
public static T ParseTo<T>(string input)
{
return (T)ParseTo(typeof(T), input);
}
public static bool TryParseTo<T>(string input, out T result)
{
result = default(T);
if (!TryParseTo(typeof(T), input, out var result2))
{
return false;
}
result = (T)result2;
return true;
}
}
public class Vector2Parser : ParserBase
{
public override Type ParseResultType => typeof(Vector2);
public override object Parse(string value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
Vector2 val = default(Vector2);
value = string.Join(' ', value.Split(new char[3] { ',', '(', ')' }, StringSplitOptions.RemoveEmptyEntries));
string[] array = value.Split(' ', StringSplitOptions.RemoveEmptyEntries);
val.x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
val.y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
return val;
}
}
public class Vector3Parser : ParserBase
{
public override Type ParseResultType => typeof(Vector3);
public override object Parse(string value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = default(Vector3);
value = string.Join(' ', value.Split(new char[3] { ',', '(', ')' }, StringSplitOptions.RemoveEmptyEntries));
string[] array = value.Split(' ', StringSplitOptions.RemoveEmptyEntries);
val.x = float.Parse(array[0].Trim(), CultureInfo.CurrentCulture);
val.y = float.Parse(array[1].Trim(), CultureInfo.CurrentCulture);
val.z = float.Parse(array[2].Trim(), CultureInfo.CurrentCulture);
return val;
}
}
}
namespace ChatCommands.BuiltinCommands
{
[CommandCategory("Admin")]
public static class AdminCommands
{
private struct SavedLists
{
public HashSet<ulong> bans;
public HashSet<ulong> ignores;
}
[HarmonyPatch(typeof(LobbyChatUILogic))]
internal static class LobbyChatUILogicPatch
{
[HarmonyPatch("HandleChatMessage")]
[HarmonyPrefix]
public static bool DontHandleIfIgnored(LobbyChatMsg message)
{
return !m_ignoredPlayers.Contains(((UserData)(ref message.sender)).SteamId);
}
}
[HarmonyPatch(typeof(LobbyController))]
internal static class LobbyControllerPatch
{
private static List<PlayerListItem> m_playerListItems;
public static void KickBannedPlayers()
{
foreach (PlayerListItem item in m_playerListItems.Where((PlayerListItem player) => m_bannedPlayers.Contains(player.PlayerSteamID)))
{
PauseManager.Instance.WriteLog("Kicked \"" + item.PlayerName + "\": banned from this lobby");
item.KickPlayer();
}
}
[HarmonyPatch("Start")]
[HarmonyPrefix]
public static void CapturePlayerlist(List<PlayerListItem> ___PlayerListItems)
{
m_playerListItems = ___PlayerListItems;
}
[HarmonyPatch("CreateClientPlayerItem")]
[HarmonyPostfix]
public static void HandleBans()
{
KickBannedPlayers();
}
}
private static HashSet<ulong> m_ignoredPlayers;
private static HashSet<ulong> m_bannedPlayers;
private static string m_savePath = Path.Combine(Paths.ConfigPath, "kestrel.straftat.chatcommands.adminlists.json");
public static void Init()
{
SavedLists? savedLists = Utils.LoadFromJsonFile<SavedLists?>(m_savePath);
m_ignoredPlayers = savedLists?.ignores ?? new HashSet<ulong>();
m_bannedPlayers = savedLists?.bans ?? new HashSet<ulong>();
}
private static void SaveToJson()
{
SavedLists obj = default(SavedLists);
obj.bans = m_bannedPlayers;
obj.ignores = m_ignoredPlayers;
Utils.SaveToJsonFile(obj, m_savePath);
}
[Command("ignore", "ignores a player, hiding their chat messages. if no steam id is provided, ignores your opponent.", CommandFlags.None)]
public static string Ignore(ulong steamID = 0uL)
{
if (steamID == 0L && (steamID = GetOpponentId()) == 0L)
{
throw new CommandException("could not get opponent's steam id");
}
if (!m_ignoredPlayers.Add(steamID))
{
throw new CommandException($"\"{steamID}\" is already ignored");
}
SaveToJson();
return $"ignored {steamID}";
}
[Command("unignore", "unignores a player. if no steam id is provided, unignores your opponent.", CommandFlags.None)]
public static string Unignore(ulong steamID = 0uL)
{
if (steamID == 0L && (steamID = GetOpponentId()) == 0L)
{
throw new CommandException("could not get opponent's steam id");
}
if (!m_ignoredPlayers.Remove(steamID))
{
throw new CommandException($"\"{steamID}\" was not ignored");
}
SaveToJson();
return $"unignored {steamID}";
}
[Command("ignorelist", "lists ignored players", CommandFlags.None)]
public static string ListIgnored()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("<u>ignored players</u>");
if (m_ignoredPlayers.Count == 0)
{
stringBuilder.AppendLine("[none]");
}
foreach (ulong ignoredPlayer in m_ignoredPlayers)
{
stringBuilder.AppendLine(ignoredPlayer.ToString());
}
return stringBuilder.ToString();
}
[Command("clearignores", "removes ALL ignores. use with caution!", CommandFlags.None)]
public static string ClearIgnores()
{
m_ignoredPlayers.Clear();
SaveToJson();
return "cleared ignorelist";
}
[Command("ban", "bans a player, automatically kicking them from any of your lobbies. if no steam id is provided, bans your opponent.", CommandFlags.None)]
public static string Ban(ulong steamID = 0uL)
{
if (steamID == 0L && (steamID = GetOpponentId()) == 0L)
{
throw new CommandException("could not get opponent's steam id");
}
if (!m_bannedPlayers.Add(steamID))
{
throw new CommandException($"\"{steamID}\" is already banned");
}
LobbyControllerPatch.KickBannedPlayers();
SaveToJson();
return $"banned {steamID}";
}
[Command("unban", "unbans a player. if no steam id is provided, unbans your opponent.", CommandFlags.None)]
public static string Unban(ulong steamID = 0uL)
{
if (steamID == 0L && (steamID = GetOpponentId()) == 0L)
{
throw new CommandException("could not get opponent's steam id");
}
if (!m_bannedPlayers.Remove(steamID))
{
throw new CommandException($"\"{steamID}\" was not banned");
}
SaveToJson();
return $"unbanned {steamID}";
}
[Command("banlist", "lists banned players", CommandFlags.None)]
public static string ListBanned()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("<u>banned players</u>");
if (m_bannedPlayers.Count == 0)
{
stringBuilder.AppendLine("[none]");
}
foreach (ulong bannedPlayer in m_bannedPlayers)
{
stringBuilder.AppendLine(bannedPlayer.ToString());
}
return stringBuilder.ToString();
}
[Command("clearbans", "removes ALL bans. use with caution!", CommandFlags.None)]
public static string ClearBans()
{
m_bannedPlayers.Clear();
SaveToJson();
return "cleared banlist";
}
private static ulong GetOpponentId()
{
return ClientInstance.Instance.Enemy()?.PlayerSteamID ?? 0;
}
}
[CommandCategory("Binding")]
public static class BindingCommands
{
private const KeyCode c_mwheelupKey = 295;
private const KeyCode c_mwheeldownKey = 296;
private const string c_mwheelup = "mwheelup";
private const string c_mwheeldown = "mwheeldown";
private static Dictionary<KeyCode, List<string>> m_binds;
private static string m_savePath = Path.Combine(Paths.ConfigPath, "kestrel.straftat.chatcommands.binds.json");
public static void Init()
{
m_binds = Utils.LoadFromJsonFile<Dictionary<KeyCode, List<string>>>(m_savePath) ?? new Dictionary<KeyCode, List<string>>();
}
public static void Update()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
if (!Cursor.visible)
{
float y = Input.mouseScrollDelta.y;
List<string> value2;
if (!(y > 0f))
{
if (y < 0f && m_binds.TryGetValue((KeyCode)296, out var value))
{
value.ForEach(Evaluator.Evaluate);
}
}
else if (m_binds.TryGetValue((KeyCode)295, out value2))
{
value2.ForEach(Evaluator.Evaluate);
}
}
if (!Input.anyKeyDown || Utils.AnyInputFieldFocused())
{
return;
}
foreach (string item in m_binds.Where((KeyValuePair<KeyCode, List<string>> bind) => Input.GetKeyDown(bind.Key)).SelectMany((KeyValuePair<KeyCode, List<string>> bind) => bind.Value))
{
Evaluator.Evaluate(item);
}
}
[Command("bind", "binds a command to a specified key", CommandFlags.None)]
public static string Bind(string key, string command)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
KeyCode key2 = ParseKey(key);
if (m_binds.TryGetValue(key2, out var value))
{
if (value.Contains(command))
{
throw new CommandException("bind already exists");
}
value.Add(command);
}
else if (!m_binds.TryAdd(key2, new List<string>(1) { command }))
{
throw new CommandException("unknown error while adding bind");
}
Utils.SaveToJsonFile(m_binds, m_savePath);
return "bound " + key.ToLower() + " -> \"" + command + "\"";
}
[Command("unbind", "removes all bindings from the specified key", CommandFlags.None)]
public static string Unbind(string key)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: 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)
KeyCode key2 = ParseKey(key);
m_binds.Remove(key2);
Utils.SaveToJsonFile(m_binds, m_savePath);
return "unbound " + key.ToLower();
}
private static KeyCode ParseKey(string key)
{
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
if (!ParserLocator.TryParseTo<KeyCode>(key, out var result) && key != "mwheelup" && key != "mwheeldown")
{
throw new CommandException("unknown key: \"" + key + "\"");
}
string text = key.ToLower();
if (!(text == "mwheelup"))
{
if (text == "mwheeldown")
{
return (KeyCode)296;
}
return result;
}
return (KeyCode)295;
}
[Command("unbindall", "removes all bindings", CommandFlags.None)]
public static string UnbindAll()
{
m_binds.Clear();
Utils.SaveToJsonFile(m_binds, m_savePath);
return "removed all bindings";
}
[Command("listbinds", "lists all bound keys", CommandFlags.None)]
[CommandAliases(new string[] { "key_listboundkeys" })]
public static string ListBinds()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Invalid comparison between Unknown and I4
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Invalid comparison between Unknown and I4
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
StringBuilder stringBuilder = new StringBuilder();
foreach (KeyValuePair<KeyCode, List<string>> bind in m_binds)
{
KeyCode key = bind.Key;
string text;
if ((int)key != 295)
{
if ((int)key == 296)
{
text = "mwheeldown";
}
else
{
KeyCode key2 = bind.Key;
text = ((object)(KeyCode)(ref key2)).ToString();
}
}
else
{
text = "mwheelup";
}
string text2 = text;
stringBuilder.Append("\"" + text2 + "\" = ");
for (int i = 0; i < bind.Value.Count; i++)
{
stringBuilder.Append("\"" + bind.Value[i] + "\"");
if (i < bind.Value.Count - 1)
{
stringBuilder.Append(", ");
}
}
stringBuilder.Append("\n");
}
string text3 = stringBuilder.ToString();
if (!(text3 == string.Empty))
{
return text3;
}
return "no binds";
}
}
[CommandCategory("Fun")]
public static class FunCommands
{
private const CommandFlags c_weaponCommandFlags = CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly;
private static bool m_weaponRainEnabled;
[Command("weapon", "spawns a weapon", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
[CommandAliases(new string[] { "w" })]
public static void Weapon(string weaponName)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
if (WeaponLoader.TryGetWeapon(weaponName, out var prefab))
{
Transform transform = ((Component)Settings.Instance.localPlayer.playerPickupScript).transform;
GameObject gameObject = ((Component)Object.Instantiate<Weapon>(prefab, transform.position, transform.rotation)).gameObject;
InstanceFinder.ServerManager.Spawn(gameObject, (NetworkConnection)null);
gameObject.GetComponent<ItemBehaviour>().DispenserDrop(Vector3.zero);
return;
}
throw new CommandException("No weapon found with name " + weaponName);
}
[Command("randomweapon", "spawns a random weapon", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
[CommandAliases(new string[] { "rw" })]
public static void RandomWeapon()
{
//IL_001b: 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_0043: Unknown result type (might be due to invalid IL or missing references)
Weapon obj = WeaponLoader.RandomWeapon();
Transform transform = ((Component)Settings.Instance.localPlayer.playerPickupScript).transform;
GameObject gameObject = ((Component)Object.Instantiate<Weapon>(obj, transform.position, transform.rotation)).gameObject;
InstanceFinder.ServerManager.Spawn(gameObject, (NetworkConnection)null);
gameObject.GetComponent<ItemBehaviour>().DispenserDrop(Vector3.zero);
}
[Command("weaponrain", "toggles weapon rain", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
public static void ToggleWeaponRain()
{
m_weaponRainEnabled = !m_weaponRainEnabled;
if (m_weaponRainEnabled)
{
((MonoBehaviour)Plugin.Instance).StartCoroutine(WeaponRain());
}
}
private static IEnumerator WeaponRain()
{
Transform playerTransform = ((Component)Settings.Instance.localPlayer.playerPickupScript).transform;
Vector3 val2 = default(Vector3);
while (m_weaponRainEnabled)
{
Weapon obj = WeaponLoader.RandomWeapon();
Vector2 val = Random.insideUnitCircle * 10f;
((Vector3)(ref val2))..ctor(playerTransform.position.x + val.x, playerTransform.position.y + 10f, playerTransform.position.z + val.y);
GameObject gameObject = ((Component)Object.Instantiate<Weapon>(obj, val2, playerTransform.rotation)).gameObject;
InstanceFinder.ServerManager.Spawn(gameObject, (NetworkConnection)null);
gameObject.GetComponent<ItemBehaviour>().DispenserDrop(Vector3.zero);
yield return (object)new WaitForSeconds(0.1f);
}
}
[Command("weapons", "spawns a number of weapons", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
public static void Weapons(string weaponName, int count)
{
//IL_0025: 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_004d: Unknown result type (might be due to invalid IL or missing references)
if (WeaponLoader.TryGetWeapon(weaponName, out var prefab))
{
Transform transform = ((Component)Settings.Instance.localPlayer.playerPickupScript).transform;
for (int i = 0; i < count; i++)
{
GameObject gameObject = ((Component)Object.Instantiate<Weapon>(prefab, transform.position, transform.rotation)).gameObject;
InstanceFinder.ServerManager.Spawn(gameObject, (NetworkConnection)null);
gameObject.GetComponent<ItemBehaviour>().DispenserDrop(Vector3.zero);
}
return;
}
throw new CommandException("No weapon found with name " + weaponName);
}
[Command("clearweapons", "removes all spawned weapons in the scene", CommandFlags.HostOnly | CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
public static void ClearWeapons()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
foreach (GameObject item in from w in ((Scene)(ref activeScene)).GetRootGameObjects()
where Object.op_Implicit((Object)(object)w.GetComponent<Weapon>()) && Object.op_Implicit((Object)(object)w.GetComponent<Rigidbody>())
select w)
{
InstanceFinder.ServerManager.Despawn(item, (DespawnType?)null);
Object.Destroy((Object)(object)item);
}
}
[Command("fling", "flings you", CommandFlags.ExplorationOnly | CommandFlags.IngameOnly)]
public static void Fling(int magnitude)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
FirstPersonController localPlayer = Settings.Instance.localPlayer;
localPlayer.CustomAddForce(((Component)localPlayer.playerCamera).transform.forward, (float)magnitude);
}
}
[CommandCategory("Input")]
public static class InputCommands
{
private static int m_mouseDownFrames;
private static ButtonControl m_buttonControl;
[Command("jump", "triggers a jump", CommandFlags.None)]
public static void Jump()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
PauseManager.Instance.chatting = false;
Settings.Instance.localPlayer.Jump(default(CallbackContext));
}
[Command("click", "triggers a click with the specified mouse button, left by default", CommandFlags.None)]
public static void Click(int button = 1)
{
m_buttonControl = (ButtonControl)(button switch
{
1 => Mouse.current.leftButton,
2 => Mouse.current.rightButton,
3 => Mouse.current.middleButton,
4 => Mouse.current.forwardButton,
5 => Mouse.current.backButton,
_ => throw new CommandException($"invalid mouse button: {button}"),
});
m_mouseDownFrames = 0;
InputSystem.onBeforeUpdate += QueueMDown;
}
private static void QueueMDown()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: 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)
InputEventPtr val = default(InputEventPtr);
NativeArray<byte> val2 = StateEvent.From((InputDevice)(object)Mouse.current, ref val, (Allocator)2);
try
{
InputControlExtensions.WriteValueIntoEvent<float>((InputControl<float>)(object)m_buttonControl, (float)(1 - m_mouseDownFrames), val);
InputSystem.QueueEvent(val);
}
finally
{
((IDisposable)val2).Dispose();
}
if (++m_mouseDownFrames > 1)
{
InputSystem.onBeforeUpdate -= QueueMDown;
}
}
}
[CommandCategory("Utility")]
public static class UtilityCommands
{
private static CommandFlags[] m_allFlags = (CommandFlags[])Enum.GetValues(typeof(CommandFlags));
[Command("echo", "outputs its input", CommandFlags.None)]
public static string Echo(string input)
{
return input;
}
[Command("eval", "evaluates its input as a command", CommandFlags.None)]
public static void Eval(string input)
{
Evaluator.Evaluate(input);
}
[Command("repeat", "executes a command a specified number of times", CommandFlags.None)]
public static void Repeat(string command, int n)
{
for (int i = 0; i < n; i++)
{
Evaluator.Evaluate(command);
}
}
[Command("concat", "concatenates two strings", CommandFlags.None)]
public static string Concat(string first, string second)
{
return first + second;
}
[Command("add", "adds the provided numbers", CommandFlags.None)]
public static float Add(float first, float second)
{
return first + second;
}
[Command("subtract", "subtracts the second number from the first", CommandFlags.None)]
public static float Subtract(float first, float second)
{
return first - second;
}
[Command("rsubtract", "subtracts the first number from the second", CommandFlags.None)]
public static float RSubtract(float first, float second)
{
return second - first;
}
[Command("multiply", "multiplies the provided numbers", CommandFlags.None)]
public static float Multiply(float first, float second)
{
return first * second;
}
[Command("divide", "divides the first number by the second", CommandFlags.None)]
public static float Divide(float first, float second)
{
return first / second;
}
[Command("rdivide", "divides the second number by the first", CommandFlags.None)]
public static float RDivide(float first, float second)
{
return second / first;
}
[Command("randint", "gets a random int in [min, max) (min inclusive, max exclusive)", CommandFlags.None)]
public static int RandInt(int minInclusive, int maxExclusive)
{
return Random.Range(minInclusive, maxExclusive);
}
[Command("randfloat", "gets a random float in [min, max] (inclusive)", CommandFlags.None)]
public static float RandFloat(float minInclusive, float maxInclusive)
{
return Random.Range(minInclusive, maxInclusive);
}
[Command("clear", "clears the chat", CommandFlags.None)]
[CommandAliases(new string[] { "cls" })]
public static void Clear()
{
ChatPatches.ClearChat();
}
[Command("say", "sends a message in chat", CommandFlags.None)]
public static void Say(string message)
{
ChatPatches.SendChatMessage(ProfanityFilterProvider.Filter.CensorString(message));
}
[Command("help", "prints command info", CommandFlags.None)]
[CommandAliases(new string[] { "h" })]
public static string Help(string commandOrCategoryName = "")
{
StringBuilder stringBuilder = new StringBuilder();
if (commandOrCategoryName != string.Empty)
{
if (CommandRegistry.TryGet(commandOrCategoryName, out var command))
{
stringBuilder.AppendHelpTextForCommand(command);
}
else
{
if (!CommandRegistry.CategoryExists(commandOrCategoryName))
{
throw new CommandException("No command or category with the name " + commandOrCategoryName + " found.");
}
Command[] array = CommandRegistry.Commands.Values.Where((Command c) => string.Equals(c.categoryName, commandOrCategoryName, StringComparison.InvariantCultureIgnoreCase)).Distinct().ToArray();
if (array.Length == 0)
{
throw new CommandException("No command or category with the name " + commandOrCategoryName + " found.");
}
stringBuilder.AppendLine("<u><size=150%><#B4F6B7>" + array[0].categoryName + "</color></size></u>").AppendLine();
foreach (Command item in array.OrderBy((Command c) => c.name))
{
stringBuilder.AppendHelpTextForCommand(item);
stringBuilder.AppendLine().AppendLine();
}
}
}
else
{
string text = "";
foreach (Command item2 in (from c in CommandRegistry.Commands.Values
orderby c.categoryName, c.name
select c).Distinct())
{
if (item2.categoryName != text)
{
text = item2.categoryName;
stringBuilder.AppendLine("<u><size=150%><#B4F6B7>" + item2.categoryName + "</color></size></u>");
stringBuilder.AppendLine();
}
stringBuilder.AppendHelpTextForCommand(item2);
stringBuilder.AppendLine().AppendLine();
}
}
return stringBuilder.ToString();
}
private static void AppendHelpTextForCommand(this StringBuilder builder, Command command)
{
if (command.isOverriden)
{
builder.Append(SmallText("(overriden) "));
}
builder.AppendLine("<u>" + command.name + "</u>");
builder.AppendLine(command.description);
builder.Append("aliases: [");
if (command.aliases.Length == 0)
{
builder.Append("none");
}
for (int i = 0; i < command.aliases.Length; i++)
{
builder.Append(command.aliases[i]);
if (i < command.aliases.Length - 1)
{
builder.Append(", ");
}
}
builder.AppendLine("]");
builder.Append("parameters: [");
if (command.maxParameters == 0)
{
builder.Append("none");
}
else
{
for (int j = 0; j < command.maxParameters; j++)
{
ParameterInfo parameterInfo = command.parameterInfos[j];
if (parameterInfo.HasDefaultValue)
{
builder.Append(SmallText("(optional) "));
}
builder.Append(parameterInfo.Name).Append(": ").Append(parameterInfo.ParameterType.Name.ToLower());
if (j < command.parameterInfos.Length - 1)
{
builder.Append(", ");
}
}
}
builder.AppendLine("]");
if (command.flags != 0)
{
builder.Append("flags: [");
for (int k = 0; k < m_allFlags.Length; k++)
{
if (m_allFlags[k] != 0 && command.flags.HasFlag(m_allFlags[k]))
{
builder.Append(m_allFlags[k]);
if (k < m_allFlags.Length - 1)
{
builder.Append(", ");
}
}
}
builder.AppendLine("]");
}
builder.Append("returns: ").Append((command.method.ReturnType == typeof(void)) ? "none" : command.method.ReturnType.Name.ToLower());
}
private static string SmallText(string text)
{
return "<alpha=#AA><voffset=0.1em><size=65%>" + text + "</size></voffset><alpha=#FF>";
}
}
[CommandCategory("Settings")]
public static class SettingsCommands
{
private static float PseudoConvarFloat(float value, Func<float> getter, Func<float, float> setter)
{
if (value == float.MinValue)
{
return getter();
}
return setter(value);
}
private static int PseudoConvarInt(int value, Func<int> getter, Func<int, int> setter)
{
if (value == int.MinValue)
{
return getter();
}
return setter(value);
}
private static float PseudoConvarSetting(float value, string settingName)
{
FieldInfo field = typeof(Settings).GetField(settingName);
Settings instance = Settings.Instance;
if (value == float.MinValue)
{
return (float)field.GetValue(instance);
}
field.SetValue(instance, value);
PlayerPrefs.SetFloat(settingName, value);
PlayerPrefs.Save();
return value;
}
[Command("maxfps", "changes max fps", CommandFlags.Silent)]
public static int MaxFps(int fps = int.MinValue)
{
return PseudoConvarInt(fps, () => Application.targetFrameRate, (int f) => Application.targetFrameRate = f);
}
[Command("fov", "changes fov", CommandFlags.Silent)]
public static float Fov(float fov = float.MinValue)
{
return PseudoConvarSetting(fov, "fovValue");
}
[Command("gamma", "changes gamma (brightness)", CommandFlags.Silent)]
public static float Gamma(float gamma = float.MinValue)
{
return PseudoConvarSetting(gamma, "brightness");
}
[Command("sensitivity", "changes sensitivity", CommandFlags.Silent)]
public static float Sensitivity(float sensitivity = float.MinValue)
{
return PseudoConvarSetting(sensitivity, "mouseSensitivity");
}
[Command("aimsensitivity", "changes aiming sensitivity", CommandFlags.Silent)]
public static float AimSensitivity(float sensitivity = float.MinValue)
{
return PseudoConvarSetting(sensitivity, "mouseAimSensitivity");
}
[Command("scopesensitivity", "changes scope sensitivity", CommandFlags.Silent)]
public static float ScopeSensitivity(float sensitivity = float.MinValue)
{
return PseudoConvarSetting(sensitivity, "mouseAimScopeSensitivity");
}
}
internal static class WeaponLoader
{
private static Dictionary<string, Weapon> m_weaponPrefabs = new Dictionary<string, Weapon>();
private static Dictionary<string, string> m_nameRedirects = new Dictionary<string, string>();
public static void Init()
{
Weapon[] array = Resources.LoadAll<Weapon>("RandomWeapons");
foreach (Weapon val in array)
{
string value = ((Object)val).name.ToUpper().Replace(" ", "");
string key = ((Component)val).GetComponent<ItemBehaviour>().weaponName.ToUpper().Replace(" ", "");
m_weaponPrefabs.TryAdd(((Object)val).name.ToUpper().Replace(" ", ""), val);
m_nameRedirects.TryAdd(key, value);
}
}
public static bool TryGetWeapon(string name, out Weapon prefab)
{
string key = name.ToUpper().Replace(" ", "");
if (!m_weaponPrefabs.TryGetValue(key, out prefab))
{
if (m_nameRedirects.TryGetValue(key, out var value))
{
return m_weaponPrefabs.TryGetValue(value, out prefab);
}
return false;
}
return true;
}
public static Weapon RandomWeapon()
{
return Utils.RandomValues(m_weaponPrefabs).Take(1).First();
}
public static Weapon[] RandomWeapons(int count)
{
return Utils.RandomValues(m_weaponPrefabs).Take(count).ToArray();
}
}
}
namespace ChatCommands.Attributes
{
[AttributeUsage(AttributeTargets.Method)]
public class CommandAliasesAttribute : Attribute
{
public readonly string[] aliases;
public CommandAliasesAttribute(params string[] aliases)
{
this.aliases = aliases;
base..ctor();
}
}
[AttributeUsage(AttributeTargets.Method)]
public class CommandAttribute : Attribute
{
public readonly string name;
public readonly string description;
public readonly CommandFlags flags;
public CommandAttribute(string name, string description, CommandFlags flags = CommandFlags.None)
{
this.name = name;
this.description = description;
this.flags = flags;
base..ctor();
}
}
[AttributeUsage(AttributeTargets.Class)]
public class CommandCategoryAttribute : Attribute
{
public readonly string name;
public CommandCategoryAttribute(string name)
{
this.name = name;
base..ctor();
}
}
[AttributeUsage(AttributeTargets.Method)]
public class CommandOverrideAttribute : Attribute
{
public readonly int priority;
public CommandOverrideAttribute(int priority = int.MaxValue)
{
this.priority = priority;
base..ctor();
}
}
}