Decompiled source of AndrewLin DnDUtil v0.0.5

AndrewLin.DnDUtil.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DnDUtil.Core;
using DnDUtil.Core.Commands;
using DnDUtil.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PurrNet;
using UnityEngine;
using UnityEngine.EventSystems;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AndrewLin.DnDUtil")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A Dungeons and Dragons mod for On-Together.")]
[assembly: AssemblyFileVersion("0.0.5.0")]
[assembly: AssemblyInformationalVersion("0.0.5+cf998f8f6bf87cfb7b80c18d4a122a93e0075215")]
[assembly: AssemblyProduct("AndrewLin.DnDUtil")]
[assembly: AssemblyTitle("AndrewLin.DnDUtil")]
[assembly: AssemblyVersion("0.0.5.0")]
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;
		}
	}
}
public static class ChatUtils
{
	public static void AddGlobalNotification(string text)
	{
		NetworkSingleton<TextChannelManager>.I.AddNotification(text);
	}

	public static string GetUserName()
	{
		return NetworkSingleton<TextChannelManager>.I.UserName;
	}

	public static void SendMessageAsync(string userName, string text, bool Islocal = false)
	{
		//IL_005d: 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)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		TextChannelManager i = NetworkSingleton<TextChannelManager>.I;
		Transform mainPlayer = i.MainPlayer;
		byte[] bytes = Encoding.Unicode.GetBytes(text.Substring(0, Math.Min(text.Length, 250)));
		byte[] bytes2 = Encoding.Unicode.GetBytes(userName);
		string text2 = Traverse.Create((object)i).Field<string>("_playerId").Value ?? "0";
		i.SendMessageAsync(bytes, bytes2, Islocal, mainPlayer.position, text2, default(RPCInfo));
	}

	public static void CleanCommand()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		LockState lockState = (LockState)(NetworkSingleton<MusicManager>.I.IsActive ? 5 : 0);
		MonoSingleton<TaskManager>.I.SetLockState(lockState);
		EventSystem.current.SetSelectedGameObject((GameObject)null);
		string text = MonoSingleton<UIManager>.I.MessageInput.text;
		if (!text.StartsWith("/help") || text == "/help dnd")
		{
			MonoSingleton<UIManager>.I.MessageInput.text = "";
		}
	}
}
namespace DnDUtil
{
	public static class BuildInfo
	{
		public const string Version = "0.0.5";
	}
	[BepInPlugin("com.andrewlin.ontogether.dndmod", "DnDUtil", "0.0.5")]
	public class Plugin : BaseUnityPlugin
	{
		public const string DefaultAnnouncerChatName = "DnDSystem";

		public const string ModGUID = "com.andrewlin.ontogether.dndmod";

		public const string ModName = "DnDUtil";

		public const string ModVersion = "0.0.5";

		public static ConfigEntry<bool>? EnableFeature { get; private set; }

		public static ConfigEntry<bool>? ShowCommand { get; private set; }

		public static ConfigEntry<string>? AnnouncerArea { get; private set; }

		public static ConfigEntry<string>? AnnouncerChatName { get; private set; }

		public static string? PlayerId { get; private set; }

		public static CommandManager? CommandProcessor { get; private set; }

		private void Awake()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)"DnDUtil v0.0.5 is loaded!");
			new Harmony("com.andrewlin.ontogether.dndmod").PatchAll(typeof(TextChannelManagerPatch));
			InitConfig();
			CommandProcessor = new CommandManager();
		}

		private void InitConfig()
		{
			EnableFeature = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableFeature", true, "Enable or disable the DnD utility features.");
			ShowCommand = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowCommand", false, "Show the command in chat when used.");
			AnnouncerChatName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "AnnouncerChatName", "DnDSystem", "The chat name to use when announcing rolls. Default is 'DnDSystem'.");
			AnnouncerArea = ((BaseUnityPlugin)this).Config.Bind<string>("General", "AnnouncerArea", "self", "The area to use when announcing rolls [self|local|global]. Default is 'self'.");
		}
	}
}
namespace DnDUtil.Patches
{
	[HarmonyPatch(typeof(TextChannelManager))]
	public class TextChannelManagerPatch
	{
		[HarmonyPatch("OnEnterPressed")]
		[HarmonyPrefix]
		public static void OnEnterPressedPrefix()
		{
			string text = MonoSingleton<UIManager>.I.MessageInput.text;
			if (!string.IsNullOrEmpty(text) && text.StartsWith('/') && Plugin.EnableFeature != null && (Plugin.EnableFeature.Value || text.Contains("usedndfeature")))
			{
				bool flag = Plugin.CommandProcessor?.ProcessInput(text) ?? false;
				ConfigEntry<bool>? showCommand = Plugin.ShowCommand;
				if (showCommand != null && !showCommand.Value && flag)
				{
					ChatUtils.CleanCommand();
				}
			}
		}
	}
}
namespace DnDUtil.Core
{
	public class CommandArgs
	{
		public static readonly CommandArgs EMPTY = new CommandArgs("", new string[0]);

		public string Name { get; }

		public string[] Args { get; }

		public CommandArgs(string name, string[] args)
		{
			Name = name;
			Args = args;
		}

		public static bool TryParse(string input, out CommandArgs result)
		{
			if (string.IsNullOrWhiteSpace(input) || !input.StartsWith('/'))
			{
				result = EMPTY;
				return false;
			}
			string text = input.Trim();
			string[] array = text.Substring(1, text.Length - 1).Split(' ', StringSplitOptions.RemoveEmptyEntries);
			string name = array[0].ToLower();
			string[] args = array.Skip(1).ToArray();
			result = new CommandArgs(name, args);
			return true;
		}

		public override string ToString()
		{
			return "/" + Name + " " + string.Join(' ', Args);
		}
	}
	public class CommandManager
	{
		private readonly ManualLogSource log = Logger.CreateLogSource("DnDUtil.CommandManager");

		private readonly Dictionary<string, IChatCommand> commands;

		public CommandManager()
		{
			IEnumerable<Type> enumerable = from t in Assembly.GetExecutingAssembly().GetTypes()
				where typeof(IChatCommand).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract
				select t;
			commands = new Dictionary<string, IChatCommand>();
			foreach (Type item in enumerable)
			{
				if (Activator.CreateInstance(item) is IChatCommand chatCommand)
				{
					commands[chatCommand.Name] = chatCommand;
					commands[chatCommand.ShortName] = chatCommand;
					log.LogInfo((object)("Loaded /" + chatCommand.Name + " (/" + chatCommand.ShortName + ")"));
				}
			}
			InitializeHelpCommand(commands);
		}

		private static void InitializeHelpCommand(Dictionary<string, IChatCommand> commands)
		{
			if (commands.TryGetValue("help", out IChatCommand value))
			{
				(value as HelpCommand)?.Initialize(commands.Values);
			}
		}

		public bool ProcessInput(string input)
		{
			if (!CommandArgs.TryParse(input, out CommandArgs result))
			{
				return false;
			}
			if (commands.TryGetValue(result.Name, out IChatCommand value))
			{
				try
				{
					value.Execute(result.Args);
				}
				catch (Exception ex)
				{
					ChatUtils.AddGlobalNotification($"Error executing '{result}': {ex.Message}");
				}
				return true;
			}
			return false;
		}
	}
}
namespace DnDUtil.Core.Commands
{
	public class HelpCommand : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "help";

		private SortedSet<IChatCommand>? commands;

		public string Name => "help";

		public string ShortName => "h";

		public string Description => "Lists all available commands.";

		public void Initialize(IEnumerable<IChatCommand> values)
		{
			commands = new SortedSet<IChatCommand>(values);
		}

		public void Execute(string[] args)
		{
			if (args.Length == 0)
			{
				ChatUtils.AddGlobalNotification("/help dnd for DnD commands");
			}
			else
			{
				if (!(args[0] == "dnd"))
				{
					return;
				}
				if (commands != null)
				{
					ChatUtils.AddGlobalNotification("DnDUtil Version (0.0.5).");
					ChatUtils.AddGlobalNotification("thunderstore.io/c/on-together/p/AndrewLin/AndrewLin_DnDUtil");
					ChatUtils.AddGlobalNotification("Available commands:");
					{
						foreach (IChatCommand command in commands)
						{
							ChatUtils.AddGlobalNotification("/" + command.Name + " (/" + command.ShortName + ") :: " + command.Description);
						}
						return;
					}
				}
				ChatUtils.AddGlobalNotification("No commands available!");
			}
		}
	}
	public interface IChatCommand : IComparable<IChatCommand>
	{
		string Name { get; }

		string ShortName => "";

		string Description { get; }

		void Execute(string[] args);

		new string ToString()
		{
			return Name;
		}

		int IComparable<IChatCommand>.CompareTo(IChatCommand? other)
		{
			if (other == null)
			{
				return 1;
			}
			return string.Compare(Name, other.Name, StringComparison.Ordinal);
		}
	}
	public class RollCommand : IChatCommand, IComparable<IChatCommand>
	{
		public string Name => "roll";

		public string ShortName => "r";

		public string Description => "Rolls a dice. E.g. '/roll 2d20 1d6' rolls 2 20-sided dice and 1 6-sided die.";

		public void Execute(string[] args)
		{
			if (args.Length == 0)
			{
				ChatUtils.AddGlobalNotification("Usage: /roll [XdY] - Rolls X dice with Y sides. Example: /roll 2d20");
				return;
			}
			foreach (string text in args)
			{
				try
				{
					List<int> values = DiceTokenToNumber(text);
					string text2 = string.Join(", ", values);
					string userName = ChatUtils.GetUserName();
					string text3 = userName + " rolled " + text + ": " + text2;
					string userName2 = Plugin.AnnouncerChatName?.Value ?? "DnDSystem";
					if (Plugin.AnnouncerArea?.Value == "self")
					{
						ChatUtils.AddGlobalNotification(text3);
					}
					else if (Plugin.AnnouncerArea?.Value == "local")
					{
						ChatUtils.SendMessageAsync(userName2, text3, Islocal: true);
					}
					else if (Plugin.AnnouncerArea?.Value == "global")
					{
						ChatUtils.SendMessageAsync(userName2, text3);
					}
				}
				catch (ArgumentException ex)
				{
					ChatUtils.AddGlobalNotification(ex.Message);
				}
			}
		}

		public static List<int> DiceTokenToNumber(string token)
		{
			if (!token.Contains('d'))
			{
				throw new ArgumentException("Invalid format '" + token + "'. Use XdY, e.g. 2d20.");
			}
			if (token.StartsWith('d'))
			{
				token = "1" + token;
			}
			string[] array = token.Split('d');
			if (array.Length != 2 || !int.TryParse(array[0], out var result) || !int.TryParse(array[1], out var result2))
			{
				throw new ArgumentException("Invalid format '" + token + "'. Use XdY, e.g. 2d20.");
			}
			Random random = new Random();
			List<int> list = new List<int>();
			for (int i = 0; i < result; i++)
			{
				list.Add(random.Next(1, result2 + 1));
			}
			return list;
		}
	}
	public class SetAnnouncerAreaCommand : IChatCommand, IComparable<IChatCommand>
	{
		public static readonly HashSet<string> ValidAreas = new HashSet<string> { "self", "local", "global" };

		public static readonly string ValidAreasText = string.Join("|", ValidAreas);

		public const string CMD = "setannouncerarea";

		public string Name => "setannouncerarea";

		public string ShortName => "saa";

		public string Description => "Set the area to use when announcing rolls: [" + ValidAreasText + "]. Current: " + (Plugin.AnnouncerArea?.Value ?? "self");

		public void Execute(string[] args)
		{
			if (Plugin.AnnouncerArea == null)
			{
				return;
			}
			if (args.Length == 0)
			{
				ChatUtils.AddGlobalNotification("Usage: /setannouncerarea [" + ValidAreasText + "] - Sets the area to use when announcing rolls.");
				return;
			}
			string text = args[0].ToLower();
			if (!ValidAreas.Contains(text))
			{
				ChatUtils.AddGlobalNotification("Invalid announcer area. Valid areas are: [" + ValidAreasText + "].");
				return;
			}
			Plugin.AnnouncerArea.Value = text;
			ChatUtils.AddGlobalNotification("Announcer area is now set to " + Plugin.AnnouncerArea.Value + ".");
		}
	}
	public class SetAnnouncerNameCommand : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "setannouncername";

		public string Name => "setannouncername";

		public string ShortName => "san";

		public string Description => "Set the name to use when sending messages to chat. Current: " + (Plugin.AnnouncerChatName?.Value ?? "DnDSystem");

		public void Execute(string[] args)
		{
			if (Plugin.AnnouncerChatName != null)
			{
				if (args.Length == 0)
				{
					ChatUtils.AddGlobalNotification("Usage: /setchatname [name] - Sets the name to use when sending messages to chat.");
					return;
				}
				Plugin.AnnouncerChatName.Value = args[0];
				ChatUtils.AddGlobalNotification("Chat name is now set to " + Plugin.AnnouncerChatName.Value + ".");
			}
		}
	}
	public class ShowDndCommand : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "showdndcommand";

		public string Name => "showdndcommand";

		public string ShortName => "sdc";

		public string Description
		{
			get
			{
				ConfigEntry<bool>? showCommand = Plugin.ShowCommand;
				return "Toggle DnDUtil show/hide DnD command in chat.If enabled, user command such as '/roll' will be shown in chat. Current: " + ((showCommand != null && showCommand.Value) ? "shown" : "hidden");
			}
		}

		public void Execute(string[] args)
		{
			if (Plugin.ShowCommand != null)
			{
				Plugin.ShowCommand.Value = !Plugin.ShowCommand.Value;
				ChatUtils.AddGlobalNotification("DnD user command is now " + (Plugin.ShowCommand.Value ? "shown" : "hidden") + ".");
			}
		}
	}
	public class UseDndFeatureCommand : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "usedndfeature";

		public string Name => "usedndfeature";

		public string ShortName => "udf";

		public string Description => "Toggle DnDUtil feature on/off. ";

		public void Execute(string[] args)
		{
			if (Plugin.EnableFeature != null)
			{
				Plugin.EnableFeature.Value = !Plugin.EnableFeature.Value;
				ChatUtils.AddGlobalNotification("DnD feature is now " + (Plugin.EnableFeature.Value ? "enabled" : "disabled") + ".");
			}
		}
	}
}