Decompiled source of Chalky v1.2.7

AndrewLin.Chalky.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Alpha;
using Alpha.Core.Command;
using Alpha.Core.Util;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Chalky.Core.Commands;
using Chalky.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using PurrNet;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AndrewLin")]
[assembly: AssemblyConfiguration("Publish")]
[assembly: AssemblyDescription("Chalky: Enlarge chalk and save/load chalkboard. Use /chalkyhelp for commands.")]
[assembly: AssemblyFileVersion("1.2.7.0")]
[assembly: AssemblyInformationalVersion("1.2.7+1902b86bd15c5c4d436b4d4523e47990ddeec1dd")]
[assembly: AssemblyProduct("AndrewLin.Chalky")]
[assembly: AssemblyTitle("AndrewLin.Chalky")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/andrewlimforfun/ot-mods")]
[assembly: AssemblyVersion("1.2.7.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;
		}
	}
}
namespace Chalky
{
	public static class BuildInfo
	{
		public const string Version = "1.2.7";
	}
	[BepInPlugin("com.andrewlin.ontogether.chalky", "Chalky", "1.2.7")]
	public class ChalkyPlugin : BaseUnityPlugin
	{
		public static readonly string DefaultChatLogPath = Path.Combine(Paths.BepInExRootPath, "on_together_chat_log.txt");

		public static int chalkySize = 2;

		public static Color? chalkyColor = null;

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

		public const string ModName = "Chalky";

		public const string ModVersion = "1.2.7";

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

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

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

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

		public static string SaveDir { get; private set; } = "";


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

		private void Awake()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Chalky v1.2.7 is loaded!");
			InitConfig();
			Harmony val = new Harmony("com.andrewlin.ontogether.chalky");
			val.PatchAll(typeof(QuadPainterGPUPatch));
			ChatCommandManager commandManager = AlphaPlugin.CommandManager;
			if (commandManager != null)
			{
				commandManager.Register((IChatCommand)(object)new ChalkyGetBoardsCommand());
			}
			ChatCommandManager commandManager2 = AlphaPlugin.CommandManager;
			if (commandManager2 != null)
			{
				commandManager2.Register((IChatCommand)(object)new ChalkyLoadBoardCommand());
			}
			ChatCommandManager commandManager3 = AlphaPlugin.CommandManager;
			if (commandManager3 != null)
			{
				commandManager3.Register((IChatCommand)(object)new ChalkySaveBoardCommand());
			}
			ChatCommandManager commandManager4 = AlphaPlugin.CommandManager;
			if (commandManager4 != null)
			{
				commandManager4.Register((IChatCommand)(object)new ChalkySetSize());
			}
			ChatCommandManager commandManager5 = AlphaPlugin.CommandManager;
			if (commandManager5 != null)
			{
				commandManager5.Register((IChatCommand)(object)new ChalkyToggleCommand());
			}
			ChatCommandManager commandManager6 = AlphaPlugin.CommandManager;
			if (commandManager6 != null)
			{
				commandManager6.Register((IChatCommand)(object)new ChalkyHostRelayCommand());
			}
		}

		private void InitConfig()
		{
			EnableFeature = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableFeature", true, "Enable or disable the mod feature.");
			ShowCommand = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowCommand", false, "Show the command in chat when used.");
			EnableHostRelay = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableHostRelay", true, "If true, the host will relay board state received from a non-host client to all other connected players.");
			BoardSaveDirectory = ((BaseUnityPlugin)this).Config.Bind<string>("Boards", "BoardSaveDirectory", "~/on-together/chalkboard", "Directory where chalkboard saves are stored. '~' expands to your home folder.");
			SaveDir = ResolvePath(BoardSaveDirectory.Value);
			Directory.CreateDirectory(SaveDir);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Board save directory: " + SaveDir));
		}

		public static string ResolvePath(string path)
		{
			if (path.StartsWith("~"))
			{
				path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + path.Substring(1);
			}
			return Path.GetFullPath(path);
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "AndrewLin.Chalky";

		public const string PLUGIN_NAME = "AndrewLin.Chalky";

		public const string PLUGIN_VERSION = "1.2.7";
	}
}
namespace Chalky.Patches
{
	[HarmonyPatch(typeof(QuadPainterGPU))]
	public class QuadPainterGPUPatch
	{
		private static ManualLogSource _log = Logger.CreateLogSource("Chalky.QPGPUP");

		private static readonly FieldInfo _pixelsField = typeof(QuadPainterGPU).GetField("_pixelsToUpdate", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo _previousUVField = typeof(QuadPainterGPU).GetField("previousUV", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo _fillTheBlanksMethod = typeof(QuadPainterGPU).GetMethod("FillTheBlanks", BindingFlags.Instance | BindingFlags.NonPublic);

		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		public static bool UpdatePrefix(QuadPainterGPU __instance)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_0263: 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)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: 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_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			if (ChalkyPlugin.EnableFeature == null || !ChalkyPlugin.EnableFeature.Value)
			{
				return true;
			}
			int chalkySize = ChalkyPlugin.chalkySize;
			if (chalkySize <= 2)
			{
				return true;
			}
			if (!__instance.IsActive || (!MonoSingleton<DrawingManager>.I.IsHaveChalk() && !MonoSingleton<DrawingManager>.I.IsEraser))
			{
				return false;
			}
			if (MonoSingleton<DrawingManager>.I.IsEraser)
			{
				return true;
			}
			Vector2 val = (Vector2)_previousUVField.GetValue(__instance);
			if (Input.GetMouseButton(0))
			{
				Ray item = MonoSingleton<ClickManager>.I.GetMousePosRay().Item1;
				RaycastHit val2 = default(RaycastHit);
				if (!Physics.Raycast(item, ref val2, 10f, 1 << LayerMask.NameToLayer("Drawing")) || (Object)(object)((Component)((RaycastHit)(ref val2)).collider).gameObject != (Object)(object)((Component)__instance).gameObject)
				{
					return false;
				}
				Vector2 textureCoord = ((RaycastHit)(ref val2)).textureCoord;
				Vector2Int gridSize = __instance.gridSize;
				float num = 2f / (float)((Vector2Int)(ref gridSize)).x;
				float num2 = 2f / (float)((Vector2Int)(ref gridSize)).y;
				int num3 = Mathf.CeilToInt((float)chalkySize / 2f);
				int chalkIndex = MonoSingleton<DrawingManager>.I.ChalkIndex;
				Vector2 val3 = default(Vector2);
				for (int i = 0; i < num3; i++)
				{
					for (int j = 0; j < num3; j++)
					{
						((Vector2)(ref val3))..ctor(textureCoord.x + (float)i * num, textureCoord.y + (float)j * num2);
						Vector2 val4 = (Vector2)((val.x > 0f) ? new Vector2(val.x + (float)i * num, val.y + (float)j * num2) : val);
						__instance.FillTheBlanksRPC(val3, val4, chalkIndex, false, false, default(RPCInfo));
						_fillTheBlanksMethod.Invoke(__instance, new object[6] { val3, val4, chalkIndex, false, false, true });
					}
				}
				_previousUVField.SetValue(__instance, textureCoord);
			}
			if (Input.GetMouseButtonUp(0))
			{
				Vector2 val5 = val;
				val5.x = -1f;
				_previousUVField.SetValue(__instance, val5);
			}
			return false;
		}

		[HarmonyPatch("GetQuadImage_Original_1")]
		[HarmonyPostfix]
		public static void RelayGetQuadImage(QuadPainterGPU __instance, RPCInfo rpcInfo)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			if (ChalkyPlugin.EnableFeature == null || !ChalkyPlugin.EnableFeature.Value || ChalkyPlugin.EnableHostRelay == null || !ChalkyPlugin.EnableHostRelay.Value || !((NetworkIdentity)__instance).isServer)
			{
				return;
			}
			PlayerID sender = rpcInfo.sender;
			if (sender == ((NetworkIdentity)__instance).localPlayerForced || sender == default(PlayerID))
			{
				return;
			}
			List<PlayerID> playerIDs = NetworkSingleton<PlayerPanelController>.I.PlayerIDs;
			int num = 0;
			foreach (PlayerID item in playerIDs)
			{
				if (!(item == sender) && !(item == ((NetworkIdentity)__instance).localPlayerForced))
				{
					__instance.GetQuadImage(item, __instance.PaintColors, default(RPCInfo));
					num++;
				}
			}
			_log.LogInfo((object)$"[BoardIO relay] Host relayed board state to {num} other player(s).");
		}
	}
}
namespace Chalky.Core
{
	public static class BoardIO
	{
		private static readonly ManualLogSource _log = Logger.CreateLogSource("Chalky.BIO");

		public static List<string> ListSavedBoards()
		{
			if (!Directory.Exists(ChalkyPlugin.SaveDir))
			{
				_log.LogWarning((object)("Save directory not found: " + ChalkyPlugin.SaveDir));
				return new List<string>();
			}
			string[] files = Directory.GetFiles(ChalkyPlugin.SaveDir, "*.chalkboard.json");
			return files.Select((string f) => Path.GetFileNameWithoutExtension(f).Replace(".chalkboard", "")).ToList();
		}

		public static int ResolveBoard(string? indexArg)
		{
			DrawingManager i = MonoSingleton<DrawingManager>.I;
			if ((Object)(object)i == (Object)null)
			{
				_log.LogError((object)"DrawingManager not found.");
				return -1;
			}
			int result;
			int num = ((string.IsNullOrEmpty(indexArg) || !int.TryParse(indexArg, out result)) ? ((int)AccessTools.Field(typeof(DrawingManager), "_boardIndex").GetValue(i)) : result);
			if (num < 0 || num >= i.QuadPainterGPUS.Count)
			{
				_log.LogError((object)($"Invalid board index {num}. " + $"Valid range: 0–{i.QuadPainterGPUS.Count - 1}. " + "Interact with a board first, or pass an explicit index."));
				return -1;
			}
			return num;
		}

		public static void SaveBoard(int index, string name)
		{
			DrawingManager i = MonoSingleton<DrawingManager>.I;
			if ((Object)(object)i == (Object)null || index < 0 || index >= i.QuadPainterGPUS.Count)
			{
				_log.LogError((object)$"SaveBoard: invalid state or index {index}");
				return;
			}
			QuadPainterGPU val = i.QuadPainterGPUS[index];
			int[][] array = val.PaintColors.Select((IntList col) => col.Ints.ToArray()).ToArray();
			string text = Path.Combine(ChalkyPlugin.SaveDir, name + ".chalkboard.json");
			File.WriteAllText(text, JsonConvert.SerializeObject((object)array));
			_log.LogInfo((object)$"Board {index} saved to {text}");
			SavePreview(val, name);
		}

		public static void LoadBoard(int index, string name)
		{
			DrawingManager i = MonoSingleton<DrawingManager>.I;
			if ((Object)(object)i == (Object)null || index < 0 || index >= i.QuadPainterGPUS.Count)
			{
				_log.LogError((object)$"LoadBoard: invalid state or index {index}");
				return;
			}
			QuadPainterGPU val = i.QuadPainterGPUS[index];
			if (!((NetworkIdentity)val).isServer)
			{
				ChatUtils.AddGlobalNotification("Relaying board to other players via the host...");
			}
			string text = Path.Combine(ChalkyPlugin.SaveDir, name + ".chalkboard.json");
			if (!File.Exists(text))
			{
				ChatUtils.AddGlobalNotification("Board file not found: " + name + ".chalkboard.json");
				_log.LogError((object)("File not found: " + text));
				return;
			}
			int[][] array = JsonConvert.DeserializeObject<int[][]>(File.ReadAllText(text));
			for (int j = 0; j < val.PaintColors.Length && j < array.Length; j++)
			{
				for (int k = 0; k < val.PaintColors[j].Ints.Count && k < array[j].Length; k++)
				{
					val.PaintColors[j].Ints[k] = array[j][k];
				}
			}
			_log.LogInfo((object)("PaintColors restored from " + text));
			RebuildRenderTexture(val, i);
			BroadcastToPlayers(val);
			_log.LogInfo((object)$"Board {index} loaded and synced to all players.");
		}

		private static void SavePreview(QuadPainterGPU board, string name)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture value = Traverse.Create((object)board).Field("_rt").GetValue<RenderTexture>();
			if ((Object)(object)value == (Object)null)
			{
				_log.LogWarning((object)"_rt is null - skipping PNG preview.");
				return;
			}
			Texture2D val = new Texture2D(((Texture)value).width, ((Texture)value).height, (TextureFormat)5, false);
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = value;
			val.ReadPixels(new Rect(0f, 0f, (float)((Texture)value).width, (float)((Texture)value).height), 0, 0);
			val.Apply();
			RenderTexture.active = active;
			string text = Path.Combine(ChalkyPlugin.SaveDir, name + ".chalkboard.png");
			File.WriteAllBytes(text, ImageConversion.EncodeToPNG(val));
			Object.Destroy((Object)(object)val);
			_log.LogInfo((object)("Preview saved to " + text));
		}

		private static void RebuildRenderTexture(QuadPainterGPU board, DrawingManager dm)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			Traverse val = Traverse.Create((object)board);
			RenderTexture value = val.Field("_rt").GetValue<RenderTexture>();
			if ((Object)(object)value == (Object)null)
			{
				_log.LogError((object)"_rt is null - cannot rebuild render texture.");
				return;
			}
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = value;
			GL.Clear(true, true, Color.clear);
			RenderTexture.active = active;
			Traverse val2 = val.Method("PaintPixel", new Type[3]
			{
				typeof(Vector2Int),
				typeof(Color),
				typeof(int)
			}, (object[])null);
			for (int i = 0; i < board.PaintColors.Length; i++)
			{
				for (int j = 0; j < board.PaintColors[i].Ints.Count; j++)
				{
					int num = board.PaintColors[i].Ints[j];
					if (num != 0)
					{
						Color color = dm.GetColor(num - 1);
						val2.GetValue(new object[3]
						{
							(object)new Vector2Int(i, j),
							color,
							num
						});
					}
				}
			}
			val.Method("RenderBatch", Array.Empty<object>()).GetValue();
			_log.LogInfo((object)"RenderTexture rebuilt from PaintColors.");
		}

		private static void BroadcastToPlayers(QuadPainterGPU board)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerID> playerIDs = NetworkSingleton<PlayerPanelController>.I.PlayerIDs;
			if (((NetworkIdentity)board).isServer)
			{
				BroadcastToAllPlayers(board);
				return;
			}
			PlayerID? val = PlayerUtils.GetHost()?.PlayerID;
			if (val.HasValue)
			{
				board.GetQuadImage(val.Value, board.PaintColors, default(RPCInfo));
				_log.LogInfo((object)"Sent board state to host for relay.");
			}
			else
			{
				_log.LogWarning((object)"Could not find host player in PlayerIDs.");
				ChatUtils.AddGlobalNotification("Could not find host player to relay board. Broadcast to everyone");
				BroadcastToAllPlayers(board);
			}
		}

		private static void BroadcastToAllPlayers(QuadPainterGPU board)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerID> playerIDs = NetworkSingleton<PlayerPanelController>.I.PlayerIDs;
			int num = 0;
			foreach (PlayerID item in playerIDs)
			{
				board.GetQuadImage(item, board.PaintColors, default(RPCInfo));
				num++;
			}
			_log.LogInfo((object)$"Broadcast to {num} player(s).");
		}
	}
}
namespace Chalky.Core.Commands
{
	public class ChalkyGetBoardsCommand : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "chalkygetboards";

		public string Name => "chalkygetboards";

		public string ShortName => "cgb";

		public string Description => "List all saved chalkboards. Usage: /chalkygetboards.";

		public string Namespace => "chalky";

		public void Execute(string[] args)
		{
			List<string> list = BoardIO.ListSavedBoards();
			if (list.Count == 0)
			{
				ChatUtils.AddGlobalNotification("No saved chalkboards found.");
				return;
			}
			string text = string.Join(", ", list);
			ChatUtils.AddGlobalNotification("Saved chalkboards: " + text);
		}
	}
	public class ChalkyHostRelayCommand : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "chalkyhostrelay";

		public string Name => "chalkyhostrelay";

		public string ShortName => "chr";

		public string Description => "Toggle Chalky host relay on/off.";

		public string Namespace => "chalky";

		public void Execute(string[] args)
		{
			if (ChalkyPlugin.EnableHostRelay != null)
			{
				ChalkyPlugin.EnableHostRelay.Value = !ChalkyPlugin.EnableHostRelay.Value;
				ChatUtils.AddGlobalNotification("Chalky host relay is now " + (ChalkyPlugin.EnableHostRelay.Value ? "enabled" : "disabled") + ".");
			}
		}
	}
	public class ChalkyLoadBoardCommand : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "chalkyloadboard";

		public string Name => "chalkyloadboard";

		public string ShortName => "clb";

		public string Description => "Load a chalkboard from disk and sync to all players (HOST only feature). Usage: /chalkyloadboard [name] [index]. Omit [index] to use the currently active board.";

		public string Namespace => "chalky";

		public void Execute(string[] args)
		{
			string name = ((args.Length >= 1) ? args[0] : "default");
			string indexArg = ((args.Length >= 2) ? args[1] : null);
			int num = BoardIO.ResolveBoard(indexArg);
			if (num < 0)
			{
				ChatUtils.AddGlobalNotification("Could not determine board index. Interact with a board first, or pass an explicit index. e.g. /chalkyloadboard rat_king 1");
			}
			else
			{
				BoardIO.LoadBoard(num, name);
			}
		}
	}
	public class ChalkySaveBoardCommand : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "chalkysaveboard";

		public string Name => "chalkysaveboard";

		public string ShortName => "csb";

		public string Description => "Save a chalkboard to disk. Usage: /chalkysaveboard [name] [index]. Omit [index] to use the currently active board.";

		public string Namespace => "chalky";

		public void Execute(string[] args)
		{
			string text = ((args.Length >= 1) ? args[0] : "default");
			string indexArg = ((args.Length >= 2) ? args[1] : null);
			int num = BoardIO.ResolveBoard(indexArg);
			if (num < 0)
			{
				ChatUtils.AddGlobalNotification("Could not determine board index. Interact with a board first, or pass an explicit index. e.g. /chalkysaveboard rat_king 1");
				return;
			}
			BoardIO.SaveBoard(num, text);
			ChatUtils.AddGlobalNotification($"Board {num} saved as '{text}' in {ChalkyPlugin.SaveDir}");
		}
	}
	public class ChalkySetSize : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "chalkysetsize";

		public string Name => "chalkysetsize";

		public string ShortName => "css";

		public string Description => "Set the size of the chalk. Not persistent, will reset to default on game restart. Game Default: 2. Usage: /chalkysetsize [size]";

		public string Namespace => "chalky";

		public void Execute(string[] args)
		{
			if (ChalkyPlugin.EnableFeature == null)
			{
				return;
			}
			int result;
			if (args.Length == 0)
			{
				ChalkyPlugin.chalkySize = 2;
				ChatUtils.AddGlobalNotification("Reset chalk size.");
			}
			else if (int.TryParse(args[0], out result))
			{
				if (result < 1)
				{
					ChatUtils.AddGlobalNotification("Invalid size value. Please provide an integer value of 1 or greater.");
					return;
				}
				if (result == 1)
				{
					ChatUtils.AddGlobalNotification("Sorry! ): Size 1 is not possible atm. Please choose a size of 2 or greater. \nP.S. if you figure out how to do size 1 please let me know!");
					return;
				}
				ChalkyPlugin.chalkySize = result;
				ChatUtils.AddGlobalNotification($"Chalk size is now set to {ChalkyPlugin.chalkySize}.");
			}
			else
			{
				ChatUtils.AddGlobalNotification("Invalid size value. Please provide a valid integer.");
			}
		}
	}
	public class ChalkyToggleCommand : IChatCommand, IComparable<IChatCommand>
	{
		public const string CMD = "chalkytoggle";

		public string Name => "chalkytoggle";

		public string ShortName => "ct";

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

		public string Namespace => "chalky";

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