using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
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.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.DependencyInjection;
using ProjectM;
using ProjectM.Network;
using SemanticVersioning;
using Unity.Collections;
using Unity.Entities;
using UnityEngine;
using VCF.Core.Basics;
using VampireCommandFramework;
using VampireCommandFramework.Basics;
using VampireCommandFramework.Breadstone;
using VampireCommandFramework.Common;
using VampireCommandFramework.Registry;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("deca")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Framework for commands in V Rising")]
[assembly: AssemblyFileVersion("0.10.4.0")]
[assembly: AssemblyInformationalVersion("0.10.4+1.Branch.main.Sha.84c042e75c8688b731a5bcacd0ea25b572dd9893")]
[assembly: AssemblyProduct("VampireCommandFramework")]
[assembly: AssemblyTitle("VampireCommandFramework")]
[assembly: InternalsVisibleTo("VCF.Tests")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.10.4.0")]
[module: UnverifiableCode]
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;
}
}
}
namespace VampireCommandFramework
{
public class ChatCommandContext : ICommandContext
{
private static int maxMessageLength = 509;
public VChatEvent Event { get; }
public User User => Event.User;
public IServiceProvider Services { get; }
public string Name
{
get
{
//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)
User user = User;
return ((object)(FixedString64Bytes)(ref user.CharacterName)).ToString();
}
}
public bool IsAdmin => User.IsAdmin;
public ChatCommandContext(VChatEvent e)
{
Event = e;
}
public void Reply(string v)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if (v.Length > maxMessageLength)
{
v = v.Substring(0, maxMessageLength);
}
FixedString512Bytes val = FixedString512Bytes.op_Implicit(v);
ServerChatUtils.SendSystemMessageToClient(VWorld.Server.EntityManager, User, ref val);
}
public CommandException Error(string LogMessage)
{
return new CommandException(LogMessage);
}
}
public static class Color
{
public static string Red = "red";
public static string Primary = "#d25";
public static string White = "#eee";
public static string LightGrey = "#bbf";
public static string Yellow = "#dd0";
public static string DarkGreen = "#0c0";
public static string Green = "#4c4";
public static string Command = "#4ED";
public static string Beige = "#fed";
public static string Gold = "#eb0";
public static string Lavender = "#c5d";
public static string Pink = "#faf";
public static string Periwinkle = "#52d";
public static string Teal = "#3ac";
public static string LightRed = "#f45";
public static string LightPurple = "#84c";
public static string Lilac = "#b9f";
public static string LightPink = "#EED";
public static string SoftBGrey = "#eef";
public static string AdminUsername = "#afa";
public static string ClanName = "#59e";
public static string LightBlood = "#f44";
public static string Blood = "#c24";
public static string LightChaos = "#faf";
public static string Chaos = "#d5e";
public static string LightUnholy = "#bd3";
public static string Unholy = "#4c0";
public static string LightIllusion = "#bfd";
public static string Illusion = "#3db";
public static string LightFrost = "#aef";
public static string Frost = "#09f";
public static string LightStorm = "#fe7";
public static string Storm = "#ff5";
public static string Discord = "#78f";
public static string Global = "#8cf";
public static string ClassicUsername = "#876";
}
public abstract class CommandArgumentConverter<T> : CommandArgumentConverter<T, ICommandContext>
{
}
public abstract class CommandArgumentConverter<T, C> where C : ICommandContext
{
public abstract T Parse(C ctx, string input);
}
[AttributeUsage(AttributeTargets.Method)]
public sealed class CommandAttribute : Attribute
{
public string Name { get; }
public string ShortHand { get; }
public string Usage { get; }
public string Description { get; }
public string Id { get; }
public bool AdminOnly { get; }
public CommandAttribute(string name, string shortHand = null, string usage = null, string description = null, string id = null, bool adminOnly = false)
{
Name = name;
ShortHand = shortHand;
Usage = usage;
Description = description;
Id = id ?? Name.Replace(" ", "-");
AdminOnly = adminOnly;
}
}
[Serializable]
public class CommandException : Exception
{
public CommandException()
{
}
public CommandException(string message)
: base(message)
{
}
public CommandException(string message, Exception innerException)
: base(message, innerException)
{
}
protected CommandException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class CommandGroupAttribute : Attribute
{
public string Name { get; }
public string ShortHand { get; }
public CommandGroupAttribute(string name, string shortHand = null)
{
Name = name;
ShortHand = shortHand;
}
}
public abstract class CommandMiddleware
{
public virtual bool CanExecute(ICommandContext ctx, CommandAttribute attribute, MethodInfo method)
{
return true;
}
public virtual void BeforeExecute(ICommandContext ctx, CommandAttribute attribute, MethodInfo method)
{
}
public virtual void AfterExecute(ICommandContext ctx, CommandAttribute attribute, MethodInfo method)
{
}
}
public enum CommandResult
{
Unmatched,
UsageError,
CommandError,
InternalError,
Denied,
Success
}
public static class Format
{
public enum FormatMode
{
GameChat,
None
}
public static FormatMode Mode { get; set; }
public static string B(string input)
{
return input.Bold();
}
public static string Bold(this string input)
{
return (Mode == FormatMode.GameChat) ? ("<b>" + input + "</b>") : input;
}
public static string I(string input)
{
return input.Italic();
}
public static string Italic(this string input)
{
return (Mode == FormatMode.GameChat) ? ("<i>" + input + "</i>") : input;
}
public static string Underline(this string input)
{
return (Mode == FormatMode.GameChat) ? ("<u>" + input + "</u>") : input;
}
public static string Color(this string input, string color)
{
return (Mode == FormatMode.GameChat) ? $"<color={color}>{input}</color>" : input;
}
public static string Size(this string input, int size)
{
return (Mode == FormatMode.GameChat) ? $"<size={size}>{input}</size>" : input;
}
public static string Small(this string input)
{
return input.Size(10);
}
public static string Normal(this string input)
{
return input.Size(16);
}
public static string Medium(this string input)
{
return input.Size(20);
}
public static string Large(this string input)
{
return input.Size(24);
}
}
public interface ICommandContext
{
IServiceProvider Services { get; }
string Name { get; }
bool IsAdmin { get; }
CommandException Error(string LogMessage);
void Reply(string v);
}
public interface IConverterUsage
{
string Usage { get; }
}
[BepInPlugin("gg.deca.VampireCommandFramework", "VampireCommandFramework", "0.10.4")]
internal class Plugin : BasePlugin
{
private Harmony _harmony;
public override void Load()
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Expected O, but got Unknown
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Expected O, but got Unknown
Log.Instance = ((BasePlugin)this).Log;
if (!VWorld.IsServer)
{
((BasePlugin)this).Log.LogMessage((object)"Note: Vampire Command Framework is loading on the client but only adds functionality on the server at this time, seeing this message is not a problem or bug.");
return;
}
_harmony = new Harmony("gg.deca.VampireCommandFramework");
_harmony.PatchAll();
CommandRegistry.RegisterCommandType(typeof(HelpCommands));
CommandRegistry.RegisterCommandType(typeof(BepInExConfigCommands));
CommandRegistry.RegisterCommandType(typeof(RepeatCommands));
((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("gg.deca.VampireCommandFramework", out var value);
ManualLogSource log = ((BasePlugin)this).Log;
bool flag = default(bool);
BepInExMessageLogInterpolatedStringHandler val = new BepInExMessageLogInterpolatedStringHandler(12, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("VCF Loaded: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Version>((value != null) ? value.Metadata.Version : null);
}
log.LogMessage(val);
}
public override bool Unload()
{
_harmony.UnpatchSelf();
return true;
}
}
public static class CommandRegistry
{
internal const string DEFAULT_PREFIX = ".";
internal static CommandCache _cache = new CommandCache();
internal static Dictionary<Type, (object instance, MethodInfo tryParse, Type contextType)> _converters = new Dictionary<Type, (object, MethodInfo, Type)>();
private static List<CommandMiddleware> DEFAULT_MIDDLEWARES = new List<CommandMiddleware>
{
new BasicAdminCheck()
};
private static Dictionary<string, (string input, List<(CommandMetadata Command, object[] Args, string Error)> commands)> _pendingCommands = new Dictionary<string, (string, List<(CommandMetadata, object[], string)>)>();
private static Dictionary<string, List<(string input, CommandMetadata Command, object[] Args)>> _commandHistory = new Dictionary<string, List<(string, CommandMetadata, object[])>>();
private const int MAX_COMMAND_HISTORY = 10;
public static List<CommandMiddleware> Middlewares { get; } = new List<CommandMiddleware>
{
new BasicAdminCheck()
};
internal static Dictionary<Assembly, Dictionary<CommandMetadata, List<string>>> AssemblyCommandMap { get; } = new Dictionary<Assembly, Dictionary<CommandMetadata, List<string>>>();
internal static void Reset()
{
Middlewares.Clear();
Middlewares.AddRange(DEFAULT_MIDDLEWARES);
AssemblyCommandMap.Clear();
_converters.Clear();
_cache = new CommandCache();
}
internal static bool CanCommandExecute(ICommandContext ctx, CommandMetadata command)
{
foreach (CommandMiddleware middleware in Middlewares)
{
try
{
if (!middleware.CanExecute(ctx, command.Attribute, command.Method))
{
return false;
}
}
catch (Exception value)
{
Log.Error($"Error executing {middleware.GetType().Name.Color(Color.Gold)} {value}");
return false;
}
}
return true;
}
internal static IEnumerable<string> FindCloseMatches(ICommandContext ctx, string input)
{
if (string.IsNullOrWhiteSpace(input))
{
return Enumerable.Empty<string>();
}
string normalizedInput = input.Substring(1, input.Length - 1).ToLowerInvariant();
int maxDistance = Math.Max(3, (int)Math.Ceiling((double)normalizedInput.Length * 0.5));
List<CommandMetadata> source = AssemblyCommandMap.SelectMany((KeyValuePair<Assembly, Dictionary<CommandMetadata, List<string>>> a) => a.Value.Keys).ToList();
return from x in (from x in source.Where((CommandMetadata c) => CanCommandExecute(ctx, c)).SelectMany(delegate(CommandMetadata cmd)
{
string[] source2 = ((cmd.GroupAttribute != null) ? ((cmd.GroupAttribute.ShortHand != null) ? new string[2]
{
cmd.GroupAttribute.Name + " ",
cmd.GroupAttribute.ShortHand + " "
} : new string[1] { cmd.GroupAttribute.Name + " " }) : new string[1] { "" });
string[] commandNames = ((cmd.Attribute.ShortHand != null) ? new string[2]
{
cmd.Attribute.Name,
cmd.Attribute.ShortHand
} : new string[1] { cmd.Attribute.Name });
return source2.SelectMany((string @group) => commandNames.Select((string name) => new
{
FullName = (@group + name).ToLowerInvariant(),
Command = cmd
}));
}).Select(cmdInfo =>
{
float distance = DamerauLevenshteinDistance(normalizedInput, cmdInfo.FullName);
int maxDistance2 = Math.Max(maxDistance, (int)Math.Ceiling((double)normalizedInput.Length * 0.5));
return new
{
Command = cmdInfo.FullName,
Distance = distance,
MaxDistance = maxDistance2
};
})
where x.Distance <= (float)x.MaxDistance
orderby x.Distance
select x).DistinctBy(x => x.Command).Take(3)
select "." + x.Command;
}
private static float DamerauLevenshteinDistance(string s, string t)
{
if (string.IsNullOrEmpty(s))
{
return (!string.IsNullOrEmpty(t)) ? t.Length : 0;
}
if (string.IsNullOrEmpty(t))
{
return s.Length;
}
float[,] array = new float[s.Length + 1, t.Length + 1];
for (int i = 0; i <= s.Length; i++)
{
array[i, 0] = i;
}
for (int j = 0; j <= t.Length; j++)
{
array[0, j] = j;
}
for (int k = 1; k <= s.Length; k++)
{
for (int l = 1; l <= t.Length; l++)
{
int num = ((s[k - 1] != t[l - 1]) ? 1 : 0);
array[k, l] = Math.Min(Math.Min(array[k - 1, l] + 1f, array[k, l - 1] + 1f), array[k - 1, l - 1] + 1.5f * (float)num);
if (k > 1 && l > 1 && s[k - 1] == t[l - 2] && s[k - 2] == t[l - 1])
{
array[k, l] = Math.Min(array[k, l], array[k - 2, l - 2] + (float)num);
}
}
}
return array[s.Length, t.Length];
}
private static void HandleBeforeExecute(ICommandContext ctx, CommandMetadata command)
{
Middlewares.ForEach(delegate(CommandMiddleware m)
{
m.BeforeExecute(ctx, command.Attribute, command.Method);
});
}
private static void HandleAfterExecute(ICommandContext ctx, CommandMetadata command)
{
Middlewares.ForEach(delegate(CommandMiddleware m)
{
m.AfterExecute(ctx, command.Attribute, command.Method);
});
}
public static CommandResult Handle(ICommandContext ctx, string input)
{
if (input.StartsWith(".") && input.Length > 1)
{
string s = input.Substring(1);
if (int.TryParse(s, out var result) && result > 0)
{
return HandleCommandSelection(ctx, result);
}
}
if (!input.StartsWith("."))
{
return CommandResult.Unmatched;
}
if (input.Trim().StartsWith(".!"))
{
HandleCommandHistory(ctx, input.Trim());
return CommandResult.Success;
}
string text = input.Substring(".".Length);
string text2 = null;
string rawInput = input;
int num = text.IndexOf(' ');
if (num > 0)
{
string potentialAssemblyName = text.Substring(0, num);
if (AssemblyCommandMap.Keys.Any((Assembly a) => a.GetName().Name.Equals(potentialAssemblyName, StringComparison.OrdinalIgnoreCase)))
{
text2 = potentialAssemblyName;
rawInput = "." + text.Substring(num + 1);
}
}
CacheResult cacheResult = null;
if (text2 != null)
{
cacheResult = _cache.GetCommandFromAssembly(rawInput, text2);
}
if (cacheResult == null || !cacheResult.IsMatched)
{
cacheResult = _cache.GetCommand(input);
}
IEnumerable<CommandMetadata> commands = cacheResult.Commands;
string[] args = cacheResult.Args;
IEnumerable<CommandMetadata> enumerable = commands;
string[] args2 = args;
if (!cacheResult.IsMatched)
{
if (!cacheResult.HasPartial)
{
return CommandResult.Unmatched;
}
foreach (CommandMetadata partialMatch in cacheResult.PartialMatches)
{
ctx.SysReply(HelpCommands.GetShortHelp(partialMatch));
}
return CommandResult.UsageError;
}
if (enumerable.Count() == 1)
{
return ExecuteCommand(ctx, enumerable.First(), args2, input);
}
List<(CommandMetadata, object[], string)> list = new List<(CommandMetadata, object[], string)>();
List<(CommandMetadata, string)> list2 = new List<(CommandMetadata, string)>();
foreach (CommandMetadata item6 in enumerable)
{
if (CanCommandExecute(ctx, item6))
{
var (flag, item, item2) = TryConvertParameters(ctx, item6, args2);
if (flag)
{
list.Add((item6, item, null));
}
else
{
list2.Add((item6, item2));
}
}
}
StringBuilder stringBuilder2;
StringBuilder.AppendInterpolatedStringHandler handler;
if (list.Count == 0)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder3 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(62, 1, stringBuilder2);
handler.AppendFormatted("[error]".Color(Color.Red));
handler.AppendLiteral(" Failed to execute command due to parameter conversion errors:");
stringBuilder3.AppendLine(ref handler);
foreach (var item7 in list2)
{
CommandMetadata item3 = item7.Item1;
string item4 = item7.Item2;
string name = item3.Assembly.GetName().Name;
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder4 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(9, 3, stringBuilder2);
handler.AppendLiteral(" - ");
handler.AppendFormatted(item3.Attribute.Name);
handler.AppendLiteral(" (");
handler.AppendFormatted(name);
handler.AppendLiteral("): ");
handler.AppendFormatted(item4);
stringBuilder4.AppendLine(ref handler);
}
ctx.SysPaginatedReply(stringBuilder);
return CommandResult.UsageError;
}
if (list.Count == 1)
{
var (command, array, _) = list[0];
AddToCommandHistory(ctx.Name, input, command, array);
return ExecuteCommandWithArgs(ctx, command, array);
}
_pendingCommands[ctx.Name] = (input, list);
StringBuilder stringBuilder5 = new StringBuilder();
stringBuilder2 = stringBuilder5;
StringBuilder stringBuilder6 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(58, 1, stringBuilder2);
handler.AppendLiteral("Multiple commands match this input. Select one by typing ");
handler.AppendFormatted(Format.B(".<#>").Color(Color.Command));
handler.AppendLiteral(":");
stringBuilder6.AppendLine(ref handler);
for (int i = 0; i < list.Count; i++)
{
CommandMetadata item5 = list[i].Item1;
string name2 = item5.Assembly.GetName().Name;
string description = item5.Attribute.Description;
stringBuilder2 = stringBuilder5;
StringBuilder stringBuilder7 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(8, 4, stringBuilder2);
handler.AppendLiteral(" ");
handler.AppendFormatted(("." + (i + 1)).Color(Color.Command));
handler.AppendLiteral(" - ");
handler.AppendFormatted(name2.Bold().Color(Color.Primary));
handler.AppendLiteral(" - ");
handler.AppendFormatted(Format.B(item5.Attribute.Name));
handler.AppendLiteral(" ");
handler.AppendFormatted(item5.Attribute.Description);
stringBuilder7.AppendLine(ref handler);
stringBuilder5.AppendLine(" " + HelpCommands.GetShortHelp(item5));
}
ctx.SysPaginatedReply(stringBuilder5);
return CommandResult.Success;
}
private static CommandResult HandleCommandSelection(ICommandContext ctx, int selectedIndex)
{
if (!_pendingCommands.TryGetValue(ctx.Name, out (string, List<(CommandMetadata, object[], string)>) value) || value.Item2.Count == 0)
{
ctx.SysReply("[error]".Color(Color.Red) + " No command selection is pending.");
return CommandResult.CommandError;
}
if (selectedIndex < 1 || selectedIndex > value.Item2.Count)
{
ctx.SysReply($"{"[error]".Color(Color.Red)} Invalid selection. Please select a number between {"1".Color(Color.Gold)} and {value.Item2.Count.ToString().Color(Color.Gold)}.");
return CommandResult.UsageError;
}
var (command, array, _) = value.Item2[selectedIndex - 1];
AddToCommandHistory(ctx.Name, value.Item1, command, array);
CommandResult result = ExecuteCommandWithArgs(ctx, command, array);
_pendingCommands.Remove(ctx.Name);
return result;
}
private static (bool Success, object[] Args, string Error) TryConvertParameters(ICommandContext ctx, CommandMetadata command, string[] args)
{
int num = ((args != null) ? args.Length : 0);
int num2 = command.Parameters.Length;
object[] array = new object[num2 + 1];
array[0] = ctx;
if (num2 == 0 && num == 0)
{
return (true, array, null);
}
if (num > num2)
{
return (false, null, "Too many parameters: expected " + num2.ToString().Color(Color.Gold) + ", got " + num.ToString().Color(Color.Gold));
}
if (num < num2)
{
if (!command.Parameters.Skip(num).All((ParameterInfo p) => p.HasDefaultValue))
{
return (false, null, "Missing required parameters: expected " + num2.ToString().Color(Color.Gold) + ", got " + num.ToString().Color(Color.Gold));
}
for (int i = num; i < num2; i++)
{
array[i + 1] = command.Parameters[i].DefaultValue;
}
}
if (num > 0)
{
for (int j = 0; j < num; j++)
{
ParameterInfo parameterInfo = command.Parameters[j];
string text = args[j];
bool flag = false;
string item = null;
try
{
if (_converters.TryGetValue(parameterInfo.ParameterType, out (object, MethodInfo, Type) value))
{
var (obj, methodInfo, type) = value;
if (!type.IsAssignableFrom(ctx.GetType()))
{
return (false, null, "INTERNAL_ERROR:Converter type " + type.Name.ToString().Color(Color.Gold) + " is not assignable from " + ctx.GetType().Name.ToString().Color(Color.Gold));
}
object[] parameters = new object[2] { ctx, text };
try
{
object obj2 = methodInfo.Invoke(obj, parameters);
array[j + 1] = obj2;
flag = true;
}
catch (TargetInvocationException ex)
{
item = ((!(ex.InnerException is CommandException ex2)) ? $"Parameter {j + 1} ({parameterInfo.Name.ToString().Color(Color.Gold)}): Unexpected error converting parameter" : $"Parameter {j + 1} ({parameterInfo.Name.ToString().Color(Color.Gold)}): {ex2.Message}");
}
catch (Exception)
{
item = $"Parameter {j + 1} ({parameterInfo.Name.ToString().Color(Color.Gold)}): Unexpected error converting parameter";
}
}
else
{
TypeConverter converter = TypeDescriptor.GetConverter(parameterInfo.ParameterType);
try
{
object obj3 = converter.ConvertFromInvariantString(text);
if (parameterInfo.ParameterType.IsEnum)
{
bool flag2 = false;
if (int.TryParse(text, out var result) && !Enum.IsDefined(parameterInfo.ParameterType, result))
{
return (false, null, $"Parameter {j + 1} ({parameterInfo.Name.ToString().Color(Color.Gold)}): Invalid enum value '{text.ToString().Color(Color.Gold)}' for {parameterInfo.ParameterType.Name.ToString().Color(Color.Gold)}");
}
}
array[j + 1] = obj3;
flag = true;
}
catch (Exception ex4)
{
item = $"Parameter {j + 1} ({parameterInfo.Name.ToString().Color(Color.Gold)}): {ex4.Message}";
}
}
}
catch (Exception ex5)
{
item = $"Parameter {j + 1} ({parameterInfo.Name.ToString().Color(Color.Gold)}): Unexpected error: {ex5.Message}";
}
if (!flag)
{
return (false, null, item);
}
}
}
return (true, array, null);
}
private static CommandResult ExecuteCommand(ICommandContext ctx, CommandMetadata command, string[] args, string input)
{
if (!command.ContextType.IsAssignableFrom(ctx?.GetType()))
{
Log.Warning($"Matched [{command.Attribute.Name.ToString().Color(Color.Gold)}] but can not assign {command.ContextType.Name.ToString().Color(Color.Gold)} from {ctx?.GetType().Name.ToString().Color(Color.Gold)}");
return CommandResult.InternalError;
}
var (flag, array, text) = TryConvertParameters(ctx, command, args);
if (!flag)
{
if (text != null && text.StartsWith("INTERNAL_ERROR:"))
{
string s = text.Substring("INTERNAL_ERROR:".Length);
Log.Warning(s);
ctx.InternalError();
return CommandResult.InternalError;
}
ctx.SysReply("[error]".Color(Color.Red) + " " + text);
return CommandResult.UsageError;
}
AddToCommandHistory(ctx.Name, input, command, array);
return ExecuteCommandWithArgs(ctx, command, array);
}
private static CommandResult ExecuteCommandWithArgs(ICommandContext ctx, CommandMetadata command, object[] commandArgs)
{
if (!command.ContextType.IsAssignableFrom(ctx?.GetType()))
{
Log.Warning($"Matched [{command.Attribute.Name.ToString().Color(Color.Gold)}] but can not assign {command.ContextType.Name.ToString().Color(Color.Gold)} from {ctx?.GetType().Name.ToString().Color(Color.Gold)}");
return CommandResult.InternalError;
}
if (command.Constructor != null && !command.ConstructorType.IsAssignableFrom(ctx?.GetType()))
{
Log.Warning($"Matched [{command.Attribute.Name.ToString().Color(Color.Gold)}] but can not assign {command.ConstructorType.Name.ToString().Color(Color.Gold)} from {ctx?.GetType().Name.ToString().Color(Color.Gold)}");
ctx.InternalError();
return CommandResult.InternalError;
}
object obj = null;
if (!command.Method.IsStatic && (!command.Method.DeclaringType.IsAbstract || !command.Method.DeclaringType.IsSealed))
{
try
{
object? obj2;
if (!(command.Constructor == null))
{
ConstructorInfo constructor = command.Constructor;
object[] parameters = new ICommandContext[1] { ctx };
obj2 = constructor.Invoke(parameters);
}
else
{
obj2 = Activator.CreateInstance(command.Method.DeclaringType);
}
obj = obj2;
}
catch (TargetInvocationException ex)
{
if (ex.InnerException is CommandException ex2)
{
ctx.SysReply(ex2.Message);
}
else
{
ctx.InternalError();
}
return CommandResult.InternalError;
}
}
if (!CanCommandExecute(ctx, command))
{
ctx.SysReply("[denied]".Color(Color.Red) + " " + command.Attribute.Name.ToString().Color(Color.Gold));
return CommandResult.Denied;
}
HandleBeforeExecute(ctx, command);
CommandException ex4 = default(CommandException);
try
{
command.Method.Invoke(obj, commandArgs);
}
catch (TargetInvocationException ex3) when (((Func<bool>)delegate
{
// Could not convert BlockContainer to single expression
ex4 = ex3.InnerException as CommandException;
return ex4 != null;
}).Invoke())
{
ctx.SysReply("[error]".Color(Color.Red) + " " + ex4.Message);
return CommandResult.CommandError;
}
catch (Exception value)
{
Log.Warning($"Hit unexpected exception executing command {command.Attribute.Id.ToString().Color(Color.Gold)}\n: {value}");
ctx.InternalError();
return CommandResult.InternalError;
}
HandleAfterExecute(ctx, command);
return CommandResult.Success;
}
private static void AddToCommandHistory(string contextName, string input, CommandMetadata command, object[] args)
{
if (!_commandHistory.TryGetValue(contextName, out List<(string, CommandMetadata, object[])> value))
{
value = new List<(string, CommandMetadata, object[])>();
_commandHistory[contextName] = value;
}
value.Insert(0, (input, command, args));
if (value.Count > 10)
{
value.RemoveAt(value.Count - 1);
}
}
private static void HandleCommandHistory(ICommandContext ctx, string input)
{
string text = input.Substring(2).Trim();
int result;
if (!_commandHistory.TryGetValue(ctx.Name, out List<(string, CommandMetadata, object[])> value) || value.Count == 0)
{
ctx.SysReply("[error]".Color(Color.Red) + " No command history available.");
}
else if (text == "list" || text == "l")
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Command history:");
for (int i = 0; i < value.Count; i++)
{
StringBuilder stringBuilder2 = stringBuilder;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder2);
handler.AppendFormatted((i + 1).ToString().Color(Color.Gold));
handler.AppendLiteral(". ");
handler.AppendFormatted(value[i].Item1.Color(Color.Command));
stringBuilder2.AppendLine(ref handler);
}
ctx.SysPaginatedReply(stringBuilder);
}
else if (int.TryParse(text, out result) && result > 0 && result <= value.Count)
{
(string, CommandMetadata, object[]) tuple = value[result - 1];
ctx.SysReply("Executing command " + result.ToString().Color(Color.Gold) + ": " + tuple.Item1.Color(Color.Command));
ExecuteCommandWithArgs(ctx, tuple.Item2, tuple.Item3);
}
else if (string.IsNullOrWhiteSpace(text))
{
(string, CommandMetadata, object[]) tuple2 = value[0];
ctx.SysReply("Repeating most recent command: " + tuple2.Item1.Color(Color.Command));
ExecuteCommandWithArgs(ctx, tuple2.Item2, tuple2.Item3);
}
else
{
ctx.SysReply($"{"[error]".Color(Color.Red)} Invalid command history selection. Use {".! list".Color(Color.Command)} to see available commands or {".! #".Color(Color.Command)} to execute a specific command.");
}
}
public static void UnregisterConverter(Type converter)
{
if (IsGenericConverterContext(converter) || IsSpecificConverterContext(converter))
{
Type[] genericTypeArguments = converter.BaseType.GenericTypeArguments;
Type type = genericTypeArguments.FirstOrDefault();
if (type == null)
{
Log.Warning("Could not resolve converter type " + converter.Name.ToString().Color(Color.Gold));
}
else if (_converters.ContainsKey(type))
{
_converters.Remove(type);
Log.Info("Unregistered converter " + converter.Name);
}
else
{
Log.Warning("Call to UnregisterConverter for a converter that was not registered. Type: " + converter.Name.ToString().Color(Color.Gold));
}
}
}
internal static bool IsGenericConverterContext(Type rootType)
{
return rootType?.BaseType?.Name == typeof(CommandArgumentConverter<>).Name;
}
internal static bool IsSpecificConverterContext(Type rootType)
{
return rootType?.BaseType?.Name == typeof(CommandArgumentConverter<, >).Name;
}
public static void RegisterConverter(Type converter)
{
bool flag = IsGenericConverterContext(converter);
bool flag2 = IsSpecificConverterContext(converter);
if (!flag && !flag2)
{
return;
}
Log.Debug($"Trying to process {converter} as specifc={flag2} generic={flag}");
object item = Activator.CreateInstance(converter);
MethodInfo method = converter.GetMethod("Parse", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod);
if (method == null)
{
Log.Error("Can't find TryParse that matches");
return;
}
Type[] genericTypeArguments = converter.BaseType.GenericTypeArguments;
Type type = genericTypeArguments.FirstOrDefault();
if (type == null)
{
Log.Error("Can't determine generic base type to convert from. ");
return;
}
Type item2 = typeof(ICommandContext);
if (flag2)
{
if (genericTypeArguments.Length != 2 || !typeof(ICommandContext).IsAssignableFrom(genericTypeArguments[1]))
{
Log.Error("Can't determine generic base type to convert from.");
return;
}
item2 = genericTypeArguments[1];
}
_converters.Add(type, (item, method, item2));
}
public static void RegisterAll()
{
RegisterAll(Assembly.GetCallingAssembly());
}
public static void RegisterAll(Assembly assembly)
{
Type[] types = assembly.GetTypes();
Type[] array = types;
foreach (Type converter in array)
{
RegisterConverter(converter);
}
Type[] array2 = types;
foreach (Type type in array2)
{
RegisterCommandType(type);
}
}
public static void RegisterCommandType(Type type)
{
CommandGroupAttribute customAttribute = type.GetCustomAttribute<CommandGroupAttribute>();
Assembly assembly = type.Assembly;
if (customAttribute != null)
{
}
MethodInfo[] methods = type.GetMethods();
ConstructorInfo customConstructor = (from c in type.GetConstructors()
where c.GetParameters().Length == 1 && typeof(ICommandContext).IsAssignableFrom(c.GetParameters().SingleOrDefault()?.ParameterType)
select c).FirstOrDefault();
MethodInfo[] array = methods;
foreach (MethodInfo method in array)
{
RegisterMethod(assembly, customAttribute, customConstructor, method);
}
}
private static void RegisterMethod(Assembly assembly, CommandGroupAttribute groupAttr, ConstructorInfo customConstructor, MethodInfo method)
{
CommandAttribute customAttribute = method.GetCustomAttribute<CommandAttribute>();
if (customAttribute == null)
{
return;
}
ParameterInfo[] parameters = method.GetParameters();
ParameterInfo parameterInfo = parameters.FirstOrDefault();
if (parameterInfo == null || parameterInfo.ParameterType is ICommandContext)
{
Log.Error("Method " + method.Name.ToString().Color(Color.Gold) + " has no CommandContext as first argument");
return;
}
ParameterInfo[] array = parameters.Skip(1).ToArray();
if (!array.All(delegate(ParameterInfo param)
{
if (_converters.ContainsKey(param.ParameterType))
{
Log.Debug($"Method {method.Name.ToString().Color(Color.Gold)} has a parameter of type {param.ParameterType.Name.ToString().Color(Color.Gold)} which is registered as a converter");
return true;
}
TypeConverter converter = TypeDescriptor.GetConverter(param.ParameterType);
if (converter == null || !converter.CanConvertFrom(typeof(string)))
{
Log.Warning($"Parameter {param.Name.ToString().Color(Color.Gold)} could not be converted, so {method.Name.ToString().Color(Color.Gold)} will be ignored.");
return false;
}
return true;
}))
{
return;
}
Type constructorType = customConstructor?.GetParameters().Single().ParameterType;
CommandMetadata commandMetadata = new CommandMetadata(customAttribute, assembly, method, customConstructor, array, parameterInfo.ParameterType, constructorType, groupAttr);
string[] array2 = ((groupAttr != null) ? ((groupAttr.ShortHand != null) ? new string[2]
{
groupAttr.Name + " ",
groupAttr.ShortHand + " "
} : new string[1] { groupAttr.Name + " " }) : new string[1] { "" });
string[] array3 = ((customAttribute.ShortHand != null) ? new string[2] { customAttribute.Name, customAttribute.ShortHand } : new string[1] { customAttribute.Name });
string text = ".";
List<string> list = new List<string>();
string[] array4 = array2;
foreach (string text2 in array4)
{
string[] array5 = array3;
foreach (string text3 in array5)
{
string text4 = text + text2 + text3;
_cache.AddCommand(text4, array, commandMetadata);
list.Add(text4);
}
}
AssemblyCommandMap.TryGetValue(assembly, out var value);
if (value == null)
{
value = new Dictionary<CommandMetadata, List<string>>();
}
value[commandMetadata] = list;
AssemblyCommandMap[assembly] = value;
}
public static void UnregisterAssembly()
{
UnregisterAssembly(Assembly.GetCallingAssembly());
}
public static void UnregisterAssembly(Assembly assembly)
{
foreach (TypeInfo definedType in assembly.DefinedTypes)
{
_cache.RemoveCommandsFromType(definedType);
UnregisterConverter(definedType);
}
AssemblyCommandMap.Remove(assembly);
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "gg.deca.VampireCommandFramework";
public const string PLUGIN_NAME = "VampireCommandFramework";
public const string PLUGIN_VERSION = "0.10.4";
}
}
namespace VampireCommandFramework.Registry
{
internal record CacheResult
{
internal IEnumerable<CommandMetadata> Commands { get; }
internal string[] Args { get; }
internal IEnumerable<CommandMetadata> PartialMatches { get; }
internal bool IsMatched => Commands != null && Commands.Any();
internal bool HasPartial => PartialMatches?.Any() ?? false;
public CacheResult(IEnumerable<CommandMetadata> commands, string[] args, IEnumerable<CommandMetadata> partialMatches)
{
Commands = commands;
Args = args ?? Array.Empty<string>();
PartialMatches = partialMatches;
}
public CacheResult(CommandMetadata command, string[] args, IEnumerable<CommandMetadata> partialMatches)
{
Commands = ((!(command != null)) ? null : new CommandMetadata[1] { command });
Args = args ?? Array.Empty<string>();
PartialMatches = partialMatches;
}
[CompilerGenerated]
protected virtual bool PrintMembers(StringBuilder builder)
{
return false;
}
}
internal class CommandCache
{
private static Dictionary<Type, HashSet<(string, int)>> _commandAssemblyMap = new Dictionary<Type, HashSet<(string, int)>>();
internal Dictionary<string, Dictionary<int, List<CommandMetadata>>> _newCache = new Dictionary<string, Dictionary<int, List<CommandMetadata>>>();
internal void AddCommand(string key, ParameterInfo[] parameters, CommandMetadata command)
{
key = key.ToLowerInvariant();
int num = parameters.Length;
int num2 = parameters.Where((ParameterInfo p) => p.HasDefaultValue).Count();
if (!_newCache.ContainsKey(key))
{
_newCache.Add(key, new Dictionary<int, List<CommandMetadata>>());
}
for (int i = num - num2; i <= num; i++)
{
_newCache[key] = _newCache.GetValueOrDefault(key, new Dictionary<int, List<CommandMetadata>>()) ?? new Dictionary<int, List<CommandMetadata>>();
if (!_newCache[key].ContainsKey(i))
{
_newCache[key][i] = new List<CommandMetadata>();
}
_newCache[key][i].Add(command);
Type declaringType = command.Method.DeclaringType;
HashSet<(string, int)> value;
HashSet<(string, int)> hashSet = (_commandAssemblyMap.TryGetValue(declaringType, out value) ? value : new HashSet<(string, int)>());
hashSet.Add((key, i));
_commandAssemblyMap[declaringType] = hashSet;
}
}
internal CacheResult GetCommand(string rawInput)
{
string text = rawInput.ToLowerInvariant();
List<CommandMetadata> list = new List<CommandMetadata>();
List<CommandMetadata> list2 = new List<CommandMetadata>();
foreach (var (text3, dictionary2) in _newCache)
{
if (!text.StartsWith(text3))
{
continue;
}
bool flag = text.Length == text3.Length;
bool flag2 = text.Length > text3.Length && text[text3.Length] == ' ';
if (!(flag || flag2))
{
continue;
}
string text4 = (flag ? "" : rawInput.Substring(text3.Length).Trim());
string[] array = ((text4.Length > 0) ? Utility.GetParts(text4).ToArray() : Array.Empty<string>());
if (dictionary2.TryGetValue(array.Length, out var value))
{
list2.AddRange(value);
if (list2.Count > 0 && array.Length != 0)
{
return new CacheResult(list2, array, null);
}
return new CacheResult(list2, Array.Empty<string>(), null);
}
list.AddRange(dictionary2.Values.SelectMany((List<CommandMetadata> x) => x));
}
if (list2.Count > 0)
{
return new CacheResult(list2, Array.Empty<string>(), null);
}
CommandMetadata command = null;
return new CacheResult(command, null, list.Distinct());
}
internal CacheResult GetCommandFromAssembly(string rawInput, string assemblyName)
{
string text = rawInput.ToLowerInvariant();
List<CommandMetadata> list = new List<CommandMetadata>();
List<CommandMetadata> list2 = new List<CommandMetadata>();
foreach (var (text3, dictionary2) in _newCache)
{
if (!text.StartsWith(text3))
{
continue;
}
bool flag = text.Length == text3.Length;
bool flag2 = text.Length > text3.Length && text[text3.Length] == ' ';
if (!(flag || flag2))
{
continue;
}
string text4 = (flag ? "" : rawInput.Substring(text3.Length).Trim());
string[] array = ((text4.Length > 0) ? Utility.GetParts(text4).ToArray() : Array.Empty<string>());
if (dictionary2.TryGetValue(array.Length, out var value))
{
list2.AddRange(value.Where((CommandMetadata cmd) => cmd.Assembly.GetName().Name.Equals(assemblyName, StringComparison.OrdinalIgnoreCase)));
if (list2.Count > 0 && array.Length != 0)
{
return new CacheResult(list2, array, null);
}
return new CacheResult(list2, Array.Empty<string>(), null);
}
list.AddRange(from cmd in dictionary2.Values.SelectMany((List<CommandMetadata> x) => x)
where cmd.Assembly.GetName().Name.Equals(assemblyName, StringComparison.OrdinalIgnoreCase)
select cmd);
}
if (list2.Count > 0)
{
return new CacheResult(list2, Array.Empty<string>(), null);
}
CommandMetadata command = null;
return new CacheResult(command, null, list.Distinct());
}
internal void RemoveCommandsFromType(Type t)
{
if (!_commandAssemblyMap.TryGetValue(t, out var value))
{
return;
}
foreach (var (key, key2) in value)
{
if (_newCache.TryGetValue(key, out var value2) && value2.TryGetValue(key2, out var value3))
{
value3.RemoveAll((CommandMetadata cmd) => cmd.Method.DeclaringType == t);
if (value3.Count == 0)
{
value2.Remove(key2);
}
}
}
_commandAssemblyMap.Remove(t);
}
internal void Clear()
{
_newCache.Clear();
}
internal void Reset()
{
throw new NotImplementedException();
}
}
internal record CommandMetadata(CommandAttribute Attribute, Assembly Assembly, MethodInfo Method, ConstructorInfo Constructor, ParameterInfo[] Parameters, Type ContextType, Type ConstructorType, CommandGroupAttribute GroupAttribute);
}
namespace VampireCommandFramework.Common
{
internal static class Log
{
internal static ManualLogSource Instance { get; set; }
public static void Warning(string s)
{
LogOrConsole(s, delegate(string s)
{
Instance.LogWarning((object)s);
});
}
public static void Error(string s)
{
LogOrConsole(s, delegate(string s)
{
Instance.LogError((object)s);
});
}
public static void Debug(string s)
{
LogOrConsole(s, delegate(string s)
{
Instance.LogDebug((object)s);
});
}
public static void Info(string s)
{
LogOrConsole(s, delegate(string s)
{
Instance.LogInfo((object)s);
});
}
private static void LogOrConsole(string message, Action<string> instanceLog)
{
if (Instance == null)
{
Console.WriteLine(message);
}
else
{
instanceLog(message);
}
}
}
internal static class Utility
{
private const int MAX_MESSAGE_SIZE = 460;
internal static List<string> GetParts(string input)
{
List<string> list = new List<string>();
if (string.IsNullOrWhiteSpace(input))
{
return list;
}
bool flag = false;
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
char c = input[i];
if (c == '\\' && i + 1 < input.Length)
{
char c2 = input[i + 1];
if (c2 == '"')
{
stringBuilder.Append(c2);
i++;
continue;
}
}
switch (c)
{
case '"':
flag = !flag;
continue;
case ' ':
if (!flag)
{
if (stringBuilder.Length > 0)
{
list.Add(stringBuilder.ToString());
stringBuilder.Clear();
}
continue;
}
break;
}
stringBuilder.Append(c);
}
if (stringBuilder.Length > 0)
{
list.Add(stringBuilder.ToString());
}
return list;
}
internal static void InternalError(this ICommandContext ctx)
{
ctx.SysReply("An internal error has occurred.");
}
internal static void SysReply(this ICommandContext ctx, string input)
{
ctx.Reply("[vcf] ".Color(Color.Primary) + input.Color(Color.Beige));
}
internal static void SysPaginatedReply(this ICommandContext ctx, StringBuilder input)
{
ctx.SysPaginatedReply(input.ToString());
}
internal static void SysPaginatedReply(this ICommandContext ctx, string input)
{
if (input.Length <= 460)
{
ctx.SysReply(input);
return;
}
string[] array = SplitIntoPages(input);
string[] array2 = array;
foreach (string text in array2)
{
string text2 = text.TrimEnd('\n', '\r', ' ');
text2 = Environment.NewLine + text2;
ctx.SysReply(text2);
}
}
internal static string[] SplitIntoPages(string rawText, int pageSize = 460)
{
List<string> list = new List<string>();
StringBuilder stringBuilder = new StringBuilder();
string[] array = rawText.Split("\n");
List<string> list2 = new List<string>();
string[] array2 = array;
foreach (string text in array2)
{
if (text.Length > pageSize)
{
string text2 = text;
while (!string.IsNullOrWhiteSpace(text2) && text2.Length > pageSize)
{
int num = text2.LastIndexOf(' ', pageSize - (int)((double)pageSize * 0.05));
if (num <= 0)
{
num = Math.Min(pageSize - 1, text2.Length);
}
list2.Add(text2.Substring(0, num));
text2 = text2.Substring(num);
}
list2.Add(text2);
}
else
{
list2.Add(text);
}
}
foreach (string item in list2)
{
if (stringBuilder.Length + item.Length > pageSize)
{
list.Add(stringBuilder.ToString());
stringBuilder.Clear();
}
stringBuilder.AppendLine(item);
}
if (stringBuilder.Length > 0)
{
list.Add(stringBuilder.ToString());
}
return list.ToArray();
}
}
}
namespace VampireCommandFramework.Breadstone
{
[HarmonyPriority(200)]
[HarmonyBefore(new string[] { "gg.deca.Bloodstone" })]
[HarmonyPatch(typeof(ChatMessageSystem), "OnUpdate")]
public static class ChatMessageSystem_Patch
{
public static void Prefix(ChatMessageSystem __instance)
{
//IL_0002: 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_0017: 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_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_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)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//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_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: 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)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: 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_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_025b: Unknown result type (might be due to invalid IL or missing references)
//IL_0260: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Unknown result type (might be due to invalid IL or missing references)
_ = __instance.__query_661171423_0;
if (1 == 0)
{
return;
}
EntityQuery _query_661171423_ = __instance.__query_661171423_0;
Enumerator<Entity> enumerator = ((EntityQuery)(ref _query_661171423_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).GetEnumerator();
while (enumerator.MoveNext())
{
Entity current = enumerator.Current;
EntityManager entityManager = ((ComponentSystemBase)__instance).EntityManager;
FromCharacter componentData = ((EntityManager)(ref entityManager)).GetComponentData<FromCharacter>(current);
entityManager = ((ComponentSystemBase)__instance).EntityManager;
User componentData2 = ((EntityManager)(ref entityManager)).GetComponentData<User>(componentData.User);
entityManager = ((ComponentSystemBase)__instance).EntityManager;
ChatMessageEvent componentData3 = ((EntityManager)(ref entityManager)).GetComponentData<ChatMessageEvent>(current);
string text = ((object)(FixedString512Bytes)(ref componentData3.MessageText)).ToString();
if (!text.StartsWith(".") || text.StartsWith(".."))
{
continue;
}
VChatEvent e = new VChatEvent(componentData.User, componentData.Character, text, componentData3.MessageType, componentData2);
ChatCommandContext ctx = new ChatCommandContext(e);
CommandResult commandResult;
try
{
commandResult = CommandRegistry.Handle(ctx, text);
}
catch (Exception value)
{
Log.Error($"Error while handling chat message {value}");
continue;
}
if (commandResult == CommandResult.Success && text.StartsWith(".help-legacy", StringComparison.InvariantCulture))
{
componentData3.MessageText = FixedString512Bytes.op_Implicit(text.Replace("-legacy", string.Empty));
entityManager = ((ComponentSystemBase)__instance).EntityManager;
((EntityManager)(ref entityManager)).SetComponentData<ChatMessageEvent>(current, componentData3);
continue;
}
if (commandResult == CommandResult.Unmatched)
{
StringBuilder stringBuilder = new StringBuilder();
StringBuilder stringBuilder2 = stringBuilder;
StringBuilder stringBuilder3 = stringBuilder2;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(19, 1, stringBuilder2);
handler.AppendLiteral("Command not found: ");
handler.AppendFormatted(text.Color(Color.Command));
stringBuilder3.AppendLine(ref handler);
string[] array = CommandRegistry.FindCloseMatches(ctx, text).ToArray();
if (array.Length != 0)
{
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder4 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(14, 1, stringBuilder2);
handler.AppendLiteral("Did you mean: ");
handler.AppendFormatted(string.Join(", ", array.Select((string c) => c.Color(Color.Command))));
stringBuilder4.AppendLine(ref handler);
}
ctx.SysReply(stringBuilder.ToString());
}
entityManager = VWorld.Server.EntityManager;
((EntityManager)(ref entityManager)).DestroyEntity(current);
}
}
}
public class VChatEvent
{
public Entity SenderUserEntity { get; }
public Entity SenderCharacterEntity { get; }
public string Message { get; }
public ChatMessageType Type { get; }
public bool Cancelled { get; private set; } = false;
public User User { get; }
internal VChatEvent(Entity userEntity, Entity characterEntity, string message, ChatMessageType type, User user)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
SenderUserEntity = userEntity;
SenderCharacterEntity = characterEntity;
Message = message;
Type = type;
User = user;
}
public void Cancel()
{
Cancelled = true;
}
}
internal static class VWorld
{
private static World _serverWorld;
public static World Server
{
get
{
if (_serverWorld != null)
{
return _serverWorld;
}
_serverWorld = GetWorld("Server") ?? throw new Exception("There is no Server world (yet). Did you install a server mod on the client?");
return _serverWorld;
}
}
public static bool IsServer => Application.productName == "VRisingServer";
public static void SendSystemMessage(this User user, string message)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: 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_0012: Unknown result type (might be due to invalid IL or missing references)
FixedString512Bytes val = FixedString512Bytes.op_Implicit(message);
ServerChatUtils.SendSystemMessageToClient(Server.EntityManager, user, ref val);
}
private static World GetWorld(string name)
{
Enumerator<World> enumerator = World.s_AllWorlds.GetEnumerator();
while (enumerator.MoveNext())
{
World current = enumerator.Current;
if (current.Name == name)
{
_serverWorld = current;
return current;
}
}
return null;
}
}
}
namespace VampireCommandFramework.Basics
{
[CommandGroup("config", null)]
public class BepInExConfigCommands
{
[Command("dump", null, null, null, null, true)]
public void DumpConfig(ICommandContext ctx, string pluginGuid)
{
var (guid, val2) = (KeyValuePair<string, PluginInfo>)(ref ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.FirstOrDefault((KeyValuePair<string, PluginInfo> x) => x.Value.Metadata.GUID.Contains(pluginGuid, StringComparison.InvariantCultureIgnoreCase)));
if (val2 != null)
{
object instance = val2.Instance;
BasePlugin val3 = (BasePlugin)((instance is BasePlugin) ? instance : null);
if (val3 != null)
{
DumpConfig(ctx, guid, val3);
return;
}
}
foreach (KeyValuePair<string, PluginInfo> plugin in ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins)
{
ctx.SysReply("Found: " + plugin.Value.Metadata.GUID);
}
throw ctx.Error("Can not find that plugin");
}
[Command("set", null, null, null, null, true)]
public void DumpConfig(ICommandContext ctx, string pluginGuid, string section, string key, string value)
{
var (text2, val2) = (KeyValuePair<string, PluginInfo>)(ref ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.FirstOrDefault((KeyValuePair<string, PluginInfo> x) => x.Value.Metadata.GUID.Contains(pluginGuid, StringComparison.InvariantCultureIgnoreCase)));
if (val2 != null)
{
object instance = val2.Instance;
BasePlugin val3 = (BasePlugin)((instance is BasePlugin) ? instance : null);
if (val3 != null)
{
var (val6, val7) = (KeyValuePair<ConfigDefinition, ConfigEntryBase>)(ref ((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)val3.Config).FirstOrDefault((KeyValuePair<ConfigDefinition, ConfigEntryBase> k) => k.Key.Section.Equals(section, StringComparison.InvariantCultureIgnoreCase) && k.Key.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase)));
if (val6 == (ConfigDefinition)null)
{
throw ctx.Error("Could not find property");
}
try
{
object value2 = TomlTypeConverter.ConvertToValue(value, val7.SettingType);
val7.SetSerializedValue(value);
if (!val3.Config.SaveOnConfigSet)
{
val3.Config.Save();
}
ctx.SysReply($"Set {val6.Key} = {value2}");
return;
}
catch (Exception)
{
throw ctx.Error($"Can not convert {value} to {val7.SettingType}");
}
}
}
foreach (KeyValuePair<string, PluginInfo> plugin in ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins)
{
ctx.SysReply("Found: " + plugin.Value.Metadata.GUID);
}
throw ctx.Error("Can not find that plugin");
}
private static void DumpConfig(ICommandContext ctx, string guid, BasePlugin plugin)
{
ConfigFile config = plugin.Config;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Path: " + config.ConfigFilePath);
StringBuilder stringBuilder2 = stringBuilder;
StringBuilder stringBuilder3 = stringBuilder2;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(33, 2, stringBuilder2);
handler.AppendLiteral("Dumping config for ");
handler.AppendFormatted(guid.Color("#f0f"));
handler.AppendLiteral(" with ");
handler.AppendFormatted(((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)config).Count());
handler.AppendLiteral(" entries");
stringBuilder3.AppendLine(ref handler);
foreach (IGrouping<string, KeyValuePair<ConfigDefinition, ConfigEntryBase>> item in from k in (IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)config
group k by k.Key.Section into k
orderby k.Key
select k)
{
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder4 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2);
handler.AppendLiteral("[");
handler.AppendFormatted(item.Key);
handler.AppendLiteral("]");
stringBuilder4.AppendLine(ref handler);
foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item2 in item)
{
item2.Deconstruct(out var key, out var value);
ConfigDefinition val = key;
ConfigEntryBase val2 = value;
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder5 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(3, 2, stringBuilder2);
handler.AppendFormatted(val.Key.Color(Color.Beige));
handler.AppendLiteral(" = ");
handler.AppendFormatted(val2.BoxedValue.ToString().Color(Color.LightGrey));
stringBuilder5.AppendLine(ref handler);
}
}
ctx.SysPaginatedReply(stringBuilder);
}
}
internal static class HelpCommands
{
private static readonly Regex _trailingLongDashRegex = new Regex("-\\d+$");
[Command("help-legacy", null, null, "Passes through a .help command that is compatible with other mods that don't use VCF.", null, false)]
public static void HelpLegacy(ICommandContext ctx, string search = null)
{
ctx.SysReply("Attempting compatible .help " + search + " for non-VCF mods.");
}
[Command("help", null, null, null, null, false)]
public static void HelpCommand(ICommandContext ctx, string search = null, string filter = null)
{
if (!string.IsNullOrEmpty(search))
{
KeyValuePair<Assembly, Dictionary<CommandMetadata, List<string>>> assembly = CommandRegistry.AssemblyCommandMap.FirstOrDefault((KeyValuePair<Assembly, Dictionary<CommandMetadata, List<string>>> x) => x.Key.GetName().Name.StartsWith(search, StringComparison.OrdinalIgnoreCase));
if (assembly.Value != null)
{
StringBuilder stringBuilder = new StringBuilder();
PrintAssemblyHelp(ctx, assembly, stringBuilder, filter);
ctx.SysPaginatedReply(stringBuilder);
return;
}
IEnumerable<KeyValuePair<CommandMetadata, List<string>>> source = CommandRegistry.AssemblyCommandMap.SelectMany((KeyValuePair<Assembly, Dictionary<CommandMetadata, List<string>>> x) => x.Value);
IEnumerable<KeyValuePair<CommandMetadata, List<string>>> source2 = source.Where((KeyValuePair<CommandMetadata, List<string>> x) => string.Equals(x.Key.Attribute.Id, search, StringComparison.InvariantCultureIgnoreCase) || string.Equals(x.Key.Attribute.Name, search, StringComparison.InvariantCultureIgnoreCase) || (x.Key.GroupAttribute != null && string.Equals(x.Key.GroupAttribute.Name, search, StringComparison.InvariantCultureIgnoreCase)) || x.Value.Contains<string>(search, StringComparer.InvariantCultureIgnoreCase));
source2 = from kvp in source2
where CommandRegistry.CanCommandExecute(ctx, kvp.Key)
where filter == null || kvp.Key.Attribute.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase)
select kvp;
if (!source2.Any())
{
throw ctx.Error("Could not find any commands for \"" + search.Color(Color.Gold) + "\"");
}
StringBuilder stringBuilder2 = new StringBuilder();
foreach (KeyValuePair<CommandMetadata, List<string>> item2 in source2)
{
GenerateFullHelp(item2.Key, item2.Value, stringBuilder2);
}
ctx.SysPaginatedReply(stringBuilder2);
return;
}
StringBuilder stringBuilder3 = new StringBuilder();
StringBuilder stringBuilder4 = stringBuilder3;
StringBuilder stringBuilder5 = stringBuilder4;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder4);
handler.AppendLiteral("Listing ");
handler.AppendFormatted(Format.B("all"));
handler.AppendLiteral(" plugins");
stringBuilder5.AppendLine(ref handler);
stringBuilder4 = stringBuilder3;
StringBuilder stringBuilder6 = stringBuilder4;
handler = new StringBuilder.AppendInterpolatedStringHandler(32, 1, stringBuilder4);
handler.AppendLiteral("Use ");
handler.AppendFormatted(Format.B(".help <plugin>").Color(Color.Gold));
handler.AppendLiteral(" for commands in that plugin");
stringBuilder6.AppendLine(ref handler);
foreach (string item3 in from x in CommandRegistry.AssemblyCommandMap
where x.Value.Keys.Any((CommandMetadata c) => CommandRegistry.CanCommandExecute(ctx, c))
select x.Key.GetName().Name into x
orderby x
select x)
{
stringBuilder4 = stringBuilder3;
StringBuilder stringBuilder7 = stringBuilder4;
handler = new StringBuilder.AppendInterpolatedStringHandler(0, 1, stringBuilder4);
handler.AppendFormatted(item3.Color(Color.Lilac));
stringBuilder7.AppendLine(ref handler);
}
ctx.SysPaginatedReply(stringBuilder3);
static void GenerateFullHelp(CommandMetadata command, List<string> aliases, StringBuilder sb)
{
StringBuilder stringBuilder8 = sb;
StringBuilder stringBuilder9 = stringBuilder8;
StringBuilder.AppendInterpolatedStringHandler handler2 = new StringBuilder.AppendInterpolatedStringHandler(1, 2, stringBuilder8);
handler2.AppendFormatted(Format.B(command.Attribute.Name).Color(Color.LightRed));
handler2.AppendLiteral(" ");
handler2.AppendFormatted(command.Attribute.Description.Color(Color.SoftBGrey));
stringBuilder9.AppendLine(ref handler2);
sb.AppendLine(GetShortHelp(command));
stringBuilder8 = sb;
StringBuilder stringBuilder10 = stringBuilder8;
handler2 = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder8);
handler2.AppendFormatted(Format.B("Aliases").Underline().Color(Color.Pink));
handler2.AppendLiteral(": ");
handler2.AppendFormatted(string.Join(", ", aliases).Italic());
stringBuilder10.AppendLine(ref handler2);
IEnumerable<Type> enumerable = from t in command.Parameters.Select((ParameterInfo p) => p.ParameterType).Distinct()
where t.IsEnum
select t;
foreach (Type item4 in enumerable)
{
stringBuilder8 = sb;
StringBuilder stringBuilder11 = stringBuilder8;
handler2 = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder8);
handler2.AppendFormatted((item4.Name + " Values").Bold().Underline().Color(Color.Pink));
handler2.AppendLiteral(": ");
handler2.AppendFormatted(string.Join(", ", Enum.GetNames(item4)).Color(Color.Command));
stringBuilder11.AppendLine(ref handler2);
}
IEnumerable<Type> enumerable2 = from p in command.Parameters.Select((ParameterInfo p) => p.ParameterType).Distinct()
where CommandRegistry._converters.ContainsKey(p)
select p;
foreach (Type item5 in enumerable2)
{
object item = CommandRegistry._converters[item5].instance;
if (item is IConverterUsage)
{
IConverterUsage converterUsage = item as IConverterUsage;
stringBuilder8 = sb;
StringBuilder stringBuilder12 = stringBuilder8;
handler2 = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder8);
handler2.AppendFormatted((item5.Name ?? "").Bold());
handler2.AppendLiteral(": ");
handler2.AppendFormatted(converterUsage.Usage);
stringBuilder12.AppendLine(ref handler2);
}
}
}
}
[Command("help-all", null, null, "Returns all plugin commands", null, false)]
public static void HelpAllCommand(ICommandContext ctx, string filter = null)
{
StringBuilder stringBuilder = new StringBuilder();
if (filter == null)
{
StringBuilder stringBuilder2 = stringBuilder;
StringBuilder stringBuilder3 = stringBuilder2;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(17, 1, stringBuilder2);
handler.AppendLiteral("Listing ");
handler.AppendFormatted(Format.B("all"));
handler.AppendLiteral(" commands");
stringBuilder3.AppendLine(ref handler);
}
else
{
StringBuilder stringBuilder2 = stringBuilder;
StringBuilder stringBuilder4 = stringBuilder2;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(36, 2, stringBuilder2);
handler.AppendLiteral("Listing ");
handler.AppendFormatted(Format.B("all"));
handler.AppendLiteral(" commands matching filter '");
handler.AppendFormatted(filter);
handler.AppendLiteral("'");
stringBuilder4.AppendLine(ref handler);
}
bool flag = false;
foreach (KeyValuePair<Assembly, Dictionary<CommandMetadata, List<string>>> item in CommandRegistry.AssemblyCommandMap.Where((KeyValuePair<Assembly, Dictionary<CommandMetadata, List<string>>> x) => x.Value.Keys.Any((CommandMetadata c) => CommandRegistry.CanCommandExecute(ctx, c) && (filter == null || GetShortHelp(c).Contains(filter, StringComparison.InvariantCultureIgnoreCase)))))
{
PrintAssemblyHelp(ctx, item, stringBuilder, filter);
flag = true;
}
if (!flag)
{
throw ctx.Error("Could not find any commands for \"" + filter + "\"");
}
ctx.SysPaginatedReply(stringBuilder);
}
private static void PrintAssemblyHelp(ICommandContext ctx, KeyValuePair<Assembly, Dictionary<CommandMetadata, List<string>>> assembly, StringBuilder sb, string filter = null)
{
string name = assembly.Key.GetName().Name;
name = _trailingLongDashRegex.Replace(name, "");
sb.AppendLine(("Commands from " + name.Medium().Color(Color.Primary) + ":").Underline());
IEnumerable<CommandMetadata> source = assembly.Value.Keys.Where((CommandMetadata c) => CommandRegistry.CanCommandExecute(ctx, c));
foreach (CommandMetadata item in source.OrderBy((CommandMetadata c) => ((c.GroupAttribute != null) ? (c.GroupAttribute.Name + " ") : "") + c.Attribute.Name))
{
string shortHelp = GetShortHelp(item);
if (filter == null || shortHelp.Contains(filter, StringComparison.InvariantCultureIgnoreCase))
{
sb.AppendLine(shortHelp);
}
}
}
internal static string GetShortHelp(CommandMetadata command)
{
CommandAttribute attribute = command.Attribute;
string text = (string.IsNullOrEmpty(command.GroupAttribute?.Name) ? string.Empty : (command.GroupAttribute.Name + " "));
string input = text + attribute.Name;
string orGenerateUsage = GetOrGenerateUsage(command);
string text2 = ".".Color(Color.Yellow);
string text3 = input.Color(Color.Beige);
return text2 + text3 + orGenerateUsage;
}
internal static string GetOrGenerateUsage(CommandMetadata command)
{
string text = command.Attribute.Usage;
if (string.IsNullOrWhiteSpace(text))
{
IEnumerable<string> values = command.Parameters.Select((ParameterInfo p) => (!p.HasDefaultValue) ? ("(" + p.Name + ")").Color(Color.LightGrey) : $"[{p.Name}={p.DefaultValue}]".Color(Color.Green));
text = string.Join(" ", values);
}
return (!string.IsNullOrWhiteSpace(text)) ? (" " + text) : string.Empty;
}
}
public static class RepeatCommands
{
[Command("!", null, null, "Repeats the most recently executed command", null, false)]
public static void RepeatLastCommand(ICommandContext ctx)
{
ctx.Error("This command is only a placeholder for the help system.");
}
[Command("! list", "! l", null, "Lists up to the last 10 commands you used.", null, false)]
public static void ListCommandHistory(ICommandContext ctx)
{
ctx.Error("This command is only a placeholder for the help system.");
}
[Command("!", null, null, "Executes a specific command from your history by its number", null, false)]
public static void ExecuteHistoryCommand(ICommandContext ctx, int previousXCommand)
{
ctx.Error("This command is only a placeholder for the help system.");
}
}
}
namespace VCF.Core.Basics
{
public class BasicAdminCheck : CommandMiddleware
{
public override bool CanExecute(ICommandContext ctx, CommandAttribute cmd, MethodInfo m)
{
return !cmd.AdminOnly || ctx.IsAdmin;
}
}
public class RolePermissionMiddleware : CommandMiddleware
{
public override bool CanExecute(ICommandContext ctx, CommandAttribute command, MethodInfo method)
{
if (ctx.IsAdmin)
{
return true;
}
RoleRepository service = ctx.Services.GetService<RoleRepository>();
return service.CanUserExecuteCommand(ctx.Name, command.Id);
}
}
public interface IRoleStorage
{
HashSet<string> Roles { get; }
void SetCommandPermission(string command, HashSet<string> roleIds);
void SetUserRoles(string userId, HashSet<string> roleIds);
HashSet<string> GetCommandPermission(string command);
HashSet<string> GetUserRoles(string userId);
}
public class RoleRepository
{
private IRoleStorage _storage;
public HashSet<string> Roles => _storage.Roles;
public RoleRepository(IRoleStorage storage)
{
_storage = storage;
}
public void AddUserToRole(string user, string role)
{
HashSet<string> hashSet = _storage.GetUserRoles(user) ?? new HashSet<string>();
hashSet.Add(role);
_storage.SetUserRoles(user, hashSet);
}
public void RemoveUserFromRole(string user, string role)
{
HashSet<string> hashSet = _storage.GetUserRoles(user) ?? new HashSet<string>();
hashSet.Remove(role);
_storage.SetUserRoles(user, hashSet);
}
public void AddRoleToCommand(string command, string role)
{
HashSet<string> hashSet = _storage.GetCommandPermission(command) ?? new HashSet<string>();
hashSet.Add(role);
_storage.SetCommandPermission(command, hashSet);
}
public void RemoveRoleFromCommand(string command, string role)
{
HashSet<string> hashSet = _storage.GetCommandPermission(command) ?? new HashSet<string>();
hashSet.Remove(role);
_storage.SetCommandPermission(command, hashSet);
}
public HashSet<string> ListUserRoles(string user)
{
return _storage.GetUserRoles(user);
}
public HashSet<string> ListCommandRoles(string command)
{
return _storage.GetCommandPermission(command);
}
public bool CanUserExecuteCommand(string user, string command)
{
HashSet<string> commandPermission = _storage.GetCommandPermission(command);
if (commandPermission == null)
{
return false;
}
HashSet<string> userRoles = _storage.GetUserRoles(user);
if (userRoles == null)
{
return false;
}
return commandPermission.Any(userRoles.Contains);
}
}
public class MemoryRoleStorage : IRoleStorage
{
private Dictionary<string, HashSet<string>> _userRoles = new Dictionary<string, HashSet<string>>();
private Dictionary<string, HashSet<string>> _commandPermissions = new Dictionary<string, HashSet<string>>();
public HashSet<string> Roles => new HashSet<string>();
public void SetCommandPermission(string command, HashSet<string> roleIds)
{
foreach (string roleId in roleIds)
{
Roles.Add(roleId);
}
_commandPermissions[command] = roleIds;
}
public void SetUserRoles(string userId, HashSet<string> roleIds)
{
_userRoles[userId] = roleIds;
}
public HashSet<string> GetCommandPermission(string command)
{
return _commandPermissions.GetValueOrDefault(command);
}
public HashSet<string> GetUserRoles(string userId)
{
HashSet<string> value;
return _userRoles.TryGetValue(userId, out value) ? value : new HashSet<string>();
}
}
public class RoleCommands
{
public record struct Role(string Name);
public record struct User(string Id);
public record struct Command(string Id);
public class RoleConverter : CommandArgumentConverter<Role>
{
public override Role Parse(ICommandContext ctx, string input)
{
RoleRepository requiredService = ctx.Services.GetRequiredService<RoleRepository>();
if (requiredService.Roles.Contains(input))
{
return new Role(input);
}
throw ctx.Error("Invalid role");
}
}
public class UserConverter : CommandArgumentConverter<User>
{
public override User Parse(ICommandContext ctx, string input)
{
return new User(input);
}
}
private RoleRepository _roleRepository = new RoleRepository(new MemoryRoleStorage());
[Command("create", null, null, null, null, false)]
public void CreateRole(ICommandContext ctx, string name)
{
_roleRepository.Roles.Add(name);
}
[Command("allow", null, null, null, null, false)]
public void AllowCommand(ICommandContext ctx, Role role, Command command)
{
_roleRepository.AddRoleToCommand(command.Id, role.Name);
}
[Command("deny", null, null, null, null, false)]
public void DenyCommand(ICommandContext ctx, Role role, Command command)
{
_roleRepository.RemoveRoleFromCommand(command.Id, role.Name);
}
[Command("assign", null, null, null, null, false)]
public void AssignUserToRole(ICommandContext ctx, User user, Role role)
{
_roleRepository.AddUserToRole(user.Id, role.Name);
}
[Command("unassign", null, null, null, null, false)]
public void UnassignUserFromRole(ICommandContext ctx, User user, Role role)
{
_roleRepository.RemoveUserFromRole(user.Id, role.Name);
}
[Command("list", null, null, null, null, false)]
public void ListRoles(ICommandContext ctx)
{
ctx.Reply("Roles: " + string.Join(", ", _roleRepository.Roles));
}
[Command("list user", null, null, null, null, false)]
public void ListRoles(ICommandContext ctx, User user)
{
ctx.Reply("Roles: " + string.Join(", ", _roleRepository.ListUserRoles(user.Id)));
}
[Command("list command", null, null, null, null, false)]
public void ListCommands(ICommandContext ctx, Command command)
{
ctx.Reply("Roles: " + string.Join(", ", _roleRepository.ListCommandRoles(command.Id)));
}
}
}