using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Shooterlatro.DebugTools;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("LuckyShotConsoleLibrary")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+4135dd1490a61fe647f2a0e54287f36471f5cf7f")]
[assembly: AssemblyProduct("LuckyShotConsoleLibrary")]
[assembly: AssemblyTitle("LuckyShotConsoleLibrary")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace LuckyShot.ConsoleLibrary
{
public sealed class ConsoleCommand
{
public string Name { get; set; }
public string Description { get; set; }
public string Usage { get; set; }
public string OwnerModId { get; set; }
public Func<IReadOnlyList<string>, DeveloperConsoleCommandResult> Handler { get; set; }
public bool IsRegistered { get; internal set; }
public override string ToString()
{
return Name;
}
}
public static class ConsoleCommands
{
private static readonly object Sync = new object();
private static readonly Dictionary<string, ConsoleCommand> Commands = new Dictionary<string, ConsoleCommand>(StringComparer.OrdinalIgnoreCase);
public static IReadOnlyCollection<ConsoleCommand> All
{
get
{
lock (Sync)
{
return new List<ConsoleCommand>(Commands.Values).AsReadOnly();
}
}
}
public static event Action<ConsoleCommand> Registered;
public static event Action<ConsoleCommand> Unregistered;
public static ConsoleCommand Register(string name, Func<IReadOnlyList<string>, DeveloperConsoleCommandResult> handler, string description = null, string usage = null, string ownerModId = null)
{
if (!IsValidName(name) || handler == null)
{
return null;
}
ConsoleCommand consoleCommand = new ConsoleCommand
{
Name = name.ToLowerInvariant(),
Description = description,
Usage = usage,
OwnerModId = (ownerModId ?? InferOwner()),
Handler = handler
};
lock (Sync)
{
if (Commands.ContainsKey(consoleCommand.Name))
{
return null;
}
Commands[consoleCommand.Name] = consoleCommand;
consoleCommand.IsRegistered = true;
}
try
{
ConsoleCommands.Registered?.Invoke(consoleCommand);
}
catch
{
}
return consoleCommand;
}
public static ConsoleCommand Register(ConsoleCommand cmd, string ownerModId = null)
{
if (cmd == null || !IsValidName(cmd.Name) || cmd.Handler == null)
{
return null;
}
lock (Sync)
{
string text = cmd.Name.ToLowerInvariant();
if (Commands.ContainsKey(text))
{
return null;
}
cmd.Name = text;
if (string.IsNullOrWhiteSpace(cmd.OwnerModId))
{
cmd.OwnerModId = ownerModId ?? InferOwner();
}
Commands[text] = cmd;
cmd.IsRegistered = true;
}
try
{
ConsoleCommands.Registered?.Invoke(cmd);
}
catch
{
}
return cmd;
}
public static bool Unregister(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return false;
}
ConsoleCommand value;
lock (Sync)
{
if (!Commands.TryGetValue(name, out value))
{
return false;
}
Commands.Remove(name);
value.IsRegistered = false;
}
try
{
ConsoleCommands.Unregistered?.Invoke(value);
}
catch
{
}
return true;
}
public static ConsoleCommand Get(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return null;
}
lock (Sync)
{
ConsoleCommand value;
return Commands.TryGetValue(name, out value) ? value : null;
}
}
public static bool IsRegistered(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return false;
}
lock (Sync)
{
return Commands.ContainsKey(name);
}
}
internal static bool TryExecute(string commandName, IReadOnlyList<string> args, out DeveloperConsoleCommandResult result)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: 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)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
result = default(DeveloperConsoleCommandResult);
if (string.IsNullOrWhiteSpace(commandName))
{
return false;
}
ConsoleCommand value;
lock (Sync)
{
if (!Commands.TryGetValue(commandName, out value))
{
return false;
}
}
try
{
DeveloperConsoleCommandResult val = value.Handler(args);
result = val;
return true;
}
catch (Exception ex)
{
result = new DeveloperConsoleCommandResult(false, value.Name + " failed: " + ex.Message, (IReadOnlyList<DeveloperConsoleHoloEntry>)null, false);
return true;
}
}
internal static string HelpAppendix()
{
List<ConsoleCommand> list;
lock (Sync)
{
list = new List<ConsoleCommand>(Commands.Values);
}
if (list.Count == 0)
{
return string.Empty;
}
list.Sort((ConsoleCommand a, ConsoleCommand b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
List<string> list2 = new List<string>();
foreach (ConsoleCommand item in list)
{
string text = item.Name + "()";
if (!string.IsNullOrWhiteSpace(item.Usage))
{
text = item.Usage;
}
else if (!string.IsNullOrWhiteSpace(item.Description))
{
text = text + " - " + item.Description;
}
list2.Add(text);
}
return "\n" + string.Join("\n", list2.ToArray());
}
public static bool IsValidName(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return false;
}
foreach (char c in name)
{
if (!char.IsLetterOrDigit(c) && c != '_')
{
return false;
}
}
return true;
}
private static string InferOwner()
{
try
{
string text = Assembly.GetCallingAssembly()?.GetName()?.Name;
return string.IsNullOrEmpty(text) ? "unknown" : text;
}
catch
{
return "unknown";
}
}
}
public static class ConsoleMarkup
{
public const string Prefix = "\u200bmd:";
public const string Green = "#50FA7B";
public const string Red = "#FF5555";
public const string Cyan = "#8BE9FD";
public const string Yellow = "#F1FA8C";
public const string Grey = "#AAAAAA";
public static string Format(string markdown)
{
return "\u200bmd:" + (markdown ?? string.Empty);
}
public static string Ok(string title, string body = null)
{
return Format(string.IsNullOrEmpty(body) ? ("**" + title + "**") : ("**" + title + "**\n" + body));
}
public static string Fail(string title, string body = null)
{
return Format("**" + title + "**" + (string.IsNullOrEmpty(body) ? string.Empty : ("\n" + body)));
}
public static string Title(string text)
{
return "# " + text;
}
public static string Bullet(string text)
{
return "- " + text;
}
public static string Code(string text)
{
return "`" + text + "`";
}
public static string Bold(string text)
{
return "**" + text + "**";
}
public static string Italic(string text)
{
return "*" + text + "*";
}
public static string Color(string hex, string text)
{
return "[c=" + hex + "]" + text + "[/c]";
}
internal static bool TryStrip(string text, out string markdown)
{
markdown = null;
if (string.IsNullOrEmpty(text) || !text.StartsWith("\u200bmd:", StringComparison.Ordinal))
{
return false;
}
markdown = text.Substring("\u200bmd:".Length);
return true;
}
internal static string ToRichText(string markdown)
{
if (markdown == null)
{
return string.Empty;
}
StringBuilder stringBuilder = new StringBuilder();
string[] array = markdown.Replace("\r\n", "\n").Split(new char[1] { '\n' });
for (int i = 0; i < array.Length; i++)
{
if (i > 0)
{
stringBuilder.Append('\n');
}
stringBuilder.Append(ConvertLine(array[i]));
}
return stringBuilder.ToString();
}
private static string ConvertLine(string line)
{
if (string.IsNullOrEmpty(line))
{
return string.Empty;
}
int i;
for (i = 0; i < line.Length && line[i] == '#'; i++)
{
}
if (i >= 1 && i <= 3 && i < line.Length && line[i] == ' ')
{
string text = ConvertInline(line.Substring(i + 1).Trim());
string text2 = i switch
{
2 => "115%",
1 => "130%",
_ => "105%",
};
return "<size=" + text2 + "><b>" + text + "</b></size>";
}
string text3 = line.TrimStart(Array.Empty<char>());
if ((text3.StartsWith("- ") || text3.StartsWith("* ")) && text3.Length > 2)
{
return "• " + ConvertInline(text3.Substring(2));
}
return ConvertInline(line);
}
private static string ConvertInline(string s)
{
if (string.IsNullOrEmpty(s))
{
return string.Empty;
}
List<Tuple<string, bool>> list = new List<Tuple<string, bool>>();
StringBuilder stringBuilder = new StringBuilder();
bool flag = false;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == '`')
{
list.Add(Tuple.Create(stringBuilder.ToString(), flag));
stringBuilder.Length = 0;
flag = !flag;
}
else
{
stringBuilder.Append(s[i]);
}
}
list.Add(Tuple.Create(stringBuilder.ToString(), flag));
StringBuilder stringBuilder2 = new StringBuilder();
foreach (Tuple<string, bool> item in list)
{
if (item.Item2)
{
stringBuilder2.Append("<color=#F1FA8C><b>" + Escape(item.Item1) + "</b></color>");
}
else
{
stringBuilder2.Append(ConvertSpans(Escape(item.Item1)));
}
}
return stringBuilder2.ToString();
}
private static string ConvertSpans(string escaped)
{
return Regex.Replace(Regex.Replace(Regex.Replace(Regex.Replace(Regex.Replace(Regex.Replace(escaped, "\\[c=([#A-Za-z0-9]+)\\](.+?)\\[/c\\]", (Match m) => (!IsHexColor(m.Groups[1].Value)) ? m.Value : ("<color=" + m.Groups[1].Value + ">" + m.Groups[2].Value + "</color>")), "\\*\\*(.+?)\\*\\*", "<b>$1</b>"), "__(.+?)__", "<u>$1</u>"), "~~(.+?)~~", "<s>$1</s>"), "(?<!\\w)\\*(?!\\s)(.+?)(?<!\\s)\\*(?!\\w)", "<i>$1</i>"), "(?<!\\w)_(?!\\s)(.+?)(?<!\\s)_(?!\\w)", "<i>$1</i>");
}
private static bool IsHexColor(string v)
{
if (string.IsNullOrEmpty(v) || !v.StartsWith("#"))
{
return false;
}
string text = v.Substring(1);
if (text.Length != 3 && text.Length != 6 && text.Length != 8)
{
return false;
}
string text2 = text;
for (int i = 0; i < text2.Length; i++)
{
if (!Uri.IsHexDigit(text2[i]))
{
return false;
}
}
return true;
}
private static string Escape(string text)
{
return (text ?? string.Empty).Replace("<", "<").Replace(">", ">");
}
}
[HarmonyPatch]
internal static class MarkupRenderPatch
{
private static MethodBase TargetMethod()
{
try
{
Type type = AccessTools.TypeByName("Shooterlatro.DebugTools.DeveloperConsole");
if (type == null)
{
return null;
}
return AccessTools.Method(type, "AppendSingleTextLine", new Type[2]
{
typeof(string),
typeof(string)
}, (Type[])null);
}
catch
{
return null;
}
}
private static bool Prefix(object __instance, string text, string color)
{
try
{
if (!ConsoleMarkup.TryStrip(text, out var markdown))
{
return true;
}
string richText = ConsoleMarkup.ToRichText(markdown);
AppendRichLine(__instance, richText, color);
return false;
}
catch
{
return true;
}
}
private static void AppendRichLine(object console, string richText, string color)
{
Type? obj = console.GetType().Assembly.GetType("TMPro.TMP_Text") ?? Type.GetType("TMPro.TMP_Text");
Type type = FindType("UnityEngine.UI.LayoutElement");
Type type2 = FindType("UnityEngine.GameObject");
if (obj == null || type == null || type2 == null || GetField(console, "_outputContainer") == null)
{
return;
}
object obj2 = CallInst(console, "CreateOutputRow", new object[1] { "TextLine" });
if (obj2 == null)
{
return;
}
object prop = GetProp(obj2, "transform");
object obj3 = CallInst(console, "CreateRowText", new object[2] { prop, 0 });
if (obj3 != null)
{
SetProp(obj3, "text", "<color=" + color + ">" + richText + "</color>");
object obj4 = obj2.GetType().GetMethod("GetComponent", new Type[1] { typeof(Type) })?.Invoke(obj2, new object[1] { type });
if (obj4 != null)
{
SetProp(obj4, "minHeight", 28f);
SetProp(obj4, "preferredHeight", 28f);
}
object prop2 = GetProp(obj3, "rectTransform");
prop2?.GetType().GetMethod("SetSizeWithCurrentAnchors")?.Invoke(prop2, new object[2] { 1, 28f });
}
}
private static Type FindType(string full)
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
try
{
Type type = assembly.GetType(full);
if (type != null)
{
return type;
}
}
catch
{
}
}
return Type.GetType(full);
}
private static object GetField(object o, string n)
{
return o.GetType().GetField(n, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(o);
}
private static object GetProp(object o, string n)
{
return o.GetType().GetProperty(n, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(o);
}
private static void SetProp(object o, string n, object v)
{
try
{
o.GetType().GetProperty(n, BindingFlags.Instance | BindingFlags.Public)?.SetValue(o, v);
}
catch
{
}
}
private static object CallInst(object instance, string n, object[] args)
{
try
{
MethodInfo[] methods = instance.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
if (methodInfo.Name != n || methodInfo.GetParameters().Length != args.Length)
{
continue;
}
ParameterInfo[] parameters = methodInfo.GetParameters();
object[] array = new object[args.Length];
for (int j = 0; j < args.Length; j++)
{
if (args[j] != null && parameters[j].ParameterType.IsEnum && args[j] is int)
{
array[j] = Enum.ToObject(parameters[j].ParameterType, (int)args[j]);
}
else
{
array[j] = args[j];
}
}
return methodInfo.Invoke(instance, array);
}
}
catch
{
}
return null;
}
private static object CallMethod(object o, string n, Type[] sig, object[] args)
{
try
{
return o.GetType().GetMethod(n, sig)?.Invoke(o, args);
}
catch
{
return null;
}
}
}
[HarmonyPatch(typeof(DeveloperConsoleCommandExecutor), "Execute")]
internal static class ExecutorPatch
{
private const string UnknownPrefix = "Unknown command '";
private static void Postfix(string input, ref DeveloperConsoleCommandResult __result)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
try
{
if (((DeveloperConsoleCommandResult)(ref __result)).Success)
{
return;
}
string text = ((DeveloperConsoleCommandResult)(ref __result)).Message ?? string.Empty;
if (IsHelpResult(input, text))
{
string text2 = ConsoleCommands.HelpAppendix();
if (!string.IsNullOrEmpty(text2))
{
__result = new DeveloperConsoleCommandResult(true, text + text2, (IReadOnlyList<DeveloperConsoleHoloEntry>)null, false);
}
}
else if (text.StartsWith("Unknown command '", StringComparison.Ordinal))
{
ParseName(input, out var name, out var args);
if (!string.IsNullOrEmpty(name) && ConsoleCommands.TryExecute(name, args, out var result))
{
__result = result;
}
}
}
catch
{
}
}
private static bool IsHelpResult(string input, string msg)
{
if (string.IsNullOrWhiteSpace(input) || string.IsNullOrEmpty(msg))
{
return false;
}
ParseName(input, out var name, out var _);
if (string.Equals(name, "help", StringComparison.OrdinalIgnoreCase))
{
return msg.IndexOf("Available commands:", StringComparison.OrdinalIgnoreCase) >= 0;
}
return false;
}
private static void ParseName(string input, out string name, out List<string> args)
{
name = null;
args = new List<string>();
try
{
string text = (input ?? string.Empty).Trim();
if (text.Length == 0)
{
return;
}
int num = text.IndexOf('(');
if (num < 0)
{
name = text.Trim();
return;
}
name = text.Substring(0, num).Trim();
int num2 = text.LastIndexOf(')');
if (num2 < num)
{
return;
}
string text2 = text.Substring(num + 1, num2 - num - 1);
if (string.IsNullOrWhiteSpace(text2))
{
return;
}
StringBuilder stringBuilder = new StringBuilder();
char c = '\0';
bool flag = false;
string text3 = text2;
foreach (char c2 in text3)
{
if (flag)
{
stringBuilder.Append(c2);
flag = false;
continue;
}
if (c != 0)
{
if (c2 == '\\')
{
flag = true;
}
else if (c2 == c)
{
c = '\0';
}
else
{
stringBuilder.Append(c2);
}
continue;
}
switch (c2)
{
case '"':
case '\'':
c = c2;
break;
case ',':
args.Add(stringBuilder.ToString().Trim());
stringBuilder.Clear();
break;
default:
stringBuilder.Append(c2);
break;
}
}
args.Add(stringBuilder.ToString().Trim());
}
catch
{
}
}
}
public static class Results
{
public static DeveloperConsoleCommandResult Ok(string message)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
return new DeveloperConsoleCommandResult(true, message, (IReadOnlyList<DeveloperConsoleHoloEntry>)null, false);
}
public static DeveloperConsoleCommandResult Err(string message)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
return new DeveloperConsoleCommandResult(false, message, (IReadOnlyList<DeveloperConsoleHoloEntry>)null, false);
}
public static DeveloperConsoleCommandResult Md(string markdown)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
return new DeveloperConsoleCommandResult(true, ConsoleMarkup.Format(markdown), (IReadOnlyList<DeveloperConsoleHoloEntry>)null, false);
}
public static DeveloperConsoleCommandResult MdErr(string markdown)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
return new DeveloperConsoleCommandResult(false, ConsoleMarkup.Format(markdown), (IReadOnlyList<DeveloperConsoleHoloEntry>)null, false);
}
public static DeveloperConsoleCommandResult OkMd(string title, string body = null)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
return new DeveloperConsoleCommandResult(true, ConsoleMarkup.Ok(title, body), (IReadOnlyList<DeveloperConsoleHoloEntry>)null, false);
}
public static DeveloperConsoleCommandResult ErrMd(string title, string body = null)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
return new DeveloperConsoleCommandResult(false, ConsoleMarkup.Fail(title, body), (IReadOnlyList<DeveloperConsoleHoloEntry>)null, false);
}
}
[BepInPlugin("com.luckyshot.wiki.consolelibrary", "LuckyShot Console Library", "1.1.0")]
public class Plugin : BaseUnityPlugin
{
private void Awake()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
new Harmony("com.luckyshot.wiki.consolelibrary").PatchAll(typeof(Plugin).Assembly);
((BaseUnityPlugin)this).Logger.LogInfo((object)"LuckyShot Console Library loaded (library only, no commands built in).");
((BaseUnityPlugin)this).Logger.LogInfo((object)"Mods: use ConsoleCommands.Register(name, handler, description, usage);");
}
}
internal static class PluginInfo
{
public const string GUID = "com.luckyshot.wiki.consolelibrary";
public const string NAME = "LuckyShot Console Library";
public const string VERSION = "1.1.0";
}
}