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 System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Chalky.Core;
using Chalky.Core.Commands;
using Chalky.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
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.Chalky")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Chalky: Some painting support for the artsy folks!")]
[assembly: AssemblyFileVersion("0.0.3.0")]
[assembly: AssemblyInformationalVersion("0.0.3+ed4467b73bdf8481fabaa61ee1b693daa39b7931")]
[assembly: AssemblyProduct("AndrewLin.Chalky")]
[assembly: AssemblyTitle("AndrewLin.Chalky")]
[assembly: AssemblyVersion("0.0.3.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
{
private static readonly Regex CommonTMPTagRegex = new Regex("<\\/?(color(=#[0-9a-fA-F]{3,8})?|#[0-9a-fA-F]{3,8}|b|i|u|s|sup|sub|size(=[\\d.]+%?)?|alpha=#[0-9a-fA-F]{2}|mark(=#[0-9a-fA-F]{3,8})?|uppercase|lowercase|smallcaps|nobr|noparse|sprite(=\\d+)?|link(=[^>]*)?)>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static void AddGlobalNotification(string text)
{
NetworkSingleton<TextChannelManager>.I.AddNotification("[Chalky] " + 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);
if (MonoSingleton<UIManager>.I.MessageInput.text != "/help")
{
MonoSingleton<UIManager>.I.MessageInput.text = "";
}
}
public static string CleanTMPTags(string input)
{
return CommonTMPTagRegex.Replace(input, string.Empty);
}
}
namespace Chalky
{
public static class BuildInfo
{
public const string Version = "0.0.3";
}
[BepInPlugin("com.andrewlin.ontogether.chalky", "Chalky", "0.0.3")]
public class Plugin : 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 = "0.0.3";
public static ConfigEntry<bool>? EnableFeature { get; private set; }
public static ConfigEntry<bool>? ShowCommand { 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; }
public static CommandManager? CommandProcessor { get; private set; }
private void Awake()
{
//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)
((BaseUnityPlugin)this).Logger.LogInfo((object)"Chalky v0.0.3 is loaded!");
InitConfig();
Harmony val = new Harmony("com.andrewlin.ontogether.chalky");
val.PatchAll(typeof(TextChannelManagerPatch));
val.PatchAll(typeof(QuadPainterGPUPatch));
CommandProcessor = new CommandManager();
}
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.");
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);
}
}
}
namespace Chalky.Patches
{
[HarmonyPatch(typeof(QuadPainterGPU))]
public class QuadPainterGPUPatch
{
private static ManualLogSource Logger = Logger.CreateLogSource("Chalky.QuadPainterGPUPatch");
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_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0210: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: 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_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: 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_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: 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)
if (Plugin.EnableFeature == null || !Plugin.EnableFeature.Value)
{
return true;
}
int chalkySize = Plugin.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))
{
RaycastHit val2 = default(RaycastHit);
if (!Physics.Raycast(MonoSingleton<ClickManager>.I.GetMousePosRay().Item1, 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(typeof(TextChannelManager))]
public class TextChannelManagerPatch
{
private static ManualLogSource Logger = Logger.CreateLogSource("Chalky.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("chalkytoggle")))
{
bool flag = Plugin.CommandProcessor?.ProcessInput(text) ?? false;
ConfigEntry<bool>? showCommand = Plugin.ShowCommand;
if (showCommand != null && !showCommand.Value && flag)
{
ChatUtils.CleanCommand();
}
}
}
}
}
namespace Chalky.Core
{
public static class BoardIO
{
private static readonly ManualLogSource Logger = Logger.CreateLogSource("Chalky");
public static List<string> ListSavedBoards()
{
if (!Directory.Exists(Plugin.SaveDir))
{
Logger.LogWarning((object)("[BoardIO] Save directory not found: " + Plugin.SaveDir));
return new List<string>();
}
return (from f in Directory.GetFiles(Plugin.SaveDir, "*.chalkboard.json")
select Path.GetFileNameWithoutExtension(f).Replace(".chalkboard", "")).ToList();
}
public static int ResolveBoard(string? indexArg)
{
DrawingManager i = MonoSingleton<DrawingManager>.I;
if ((Object)(object)i == (Object)null)
{
Logger.LogError((object)"[BoardIO] 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)
{
Logger.LogError((object)($"[BoardIO] 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)
{
Logger.LogError((object)$"[BoardIO] SaveBoard: invalid state or index {index}");
return;
}
QuadPainterGPU obj = i.QuadPainterGPUS[index];
int[][] array = obj.PaintColors.Select((IntList col) => col.Ints.ToArray()).ToArray();
string text = Path.Combine(Plugin.SaveDir, name + ".chalkboard.json");
File.WriteAllText(text, JsonConvert.SerializeObject((object)array));
Logger.LogInfo((object)$"[BoardIO] Board {index} saved to {text}");
SavePreview(obj, 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)
{
Logger.LogError((object)$"[BoardIO] LoadBoard: invalid state or index {index}");
return;
}
QuadPainterGPU val = i.QuadPainterGPUS[index];
if (!((NetworkIdentity)val).isServer)
{
ChatUtils.AddGlobalNotification("You must be the host to load a board.");
Logger.LogWarning((object)"[BoardIO] Load+sync requires you to be the host.");
return;
}
string text = Path.Combine(Plugin.SaveDir, name + ".chalkboard.json");
if (!File.Exists(text))
{
ChatUtils.AddGlobalNotification("Board file not found: " + name + ".chalkboard.json");
Logger.LogError((object)("[BoardIO] 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];
}
}
Logger.LogInfo((object)("[BoardIO] PaintColors restored from " + text));
RebuildRenderTexture(val, i);
BroadcastToPlayers(val);
Logger.LogInfo((object)$"[BoardIO] Board {index} loaded and synced to all players.");
}
private static void SavePreview(QuadPainterGPU board, string name)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Expected O, but got Unknown
//IL_0067: 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)
{
Logger.LogWarning((object)"[BoardIO] _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(Plugin.SaveDir, name + ".chalkboard.png");
File.WriteAllBytes(text, ImageConversion.EncodeToPNG(val));
Object.Destroy((Object)(object)val);
Logger.LogInfo((object)("[BoardIO] Preview saved to " + text));
}
private static void RebuildRenderTexture(QuadPainterGPU board, DrawingManager dm)
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: 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)
{
Logger.LogError((object)"[BoardIO] _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();
Logger.LogInfo((object)"[BoardIO] RenderTexture rebuilt from PaintColors.");
}
private static void BroadcastToPlayers(QuadPainterGPU board)
{
//IL_0016: 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_001d: 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)
List<PlayerID> playerIDs = NetworkSingleton<PlayerPanelController>.I.PlayerIDs;
int num = 0;
foreach (PlayerID item in playerIDs)
{
board.GetQuadImage(item, board.PaintColors, default(RPCInfo));
num++;
}
Logger.LogInfo((object)$"[BoardIO] Broadcast to {num} player(s).");
}
}
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("Chalky");
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("chalkyhelp", out IChatCommand value))
{
(value as ChalkyHelpCommand)?.Initialize(commands.Values);
}
if (commands.TryGetValue("help", out IChatCommand value2))
{
(value2 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 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 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 ChalkyHelpCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "chalkyhelp";
private SortedSet<IChatCommand>? commands;
public string Name => "chalkyhelp";
public string ShortName => "ch";
public string Description => "Lists all available commands.";
public void Initialize(IEnumerable<IChatCommand> values)
{
commands = new SortedSet<IChatCommand>(values);
}
public void Execute(string[] args)
{
if (commands == null)
{
ChatUtils.AddGlobalNotification("No commands available!");
return;
}
ChatUtils.AddGlobalNotification("Chalky Version (0.0.3).");
ChatUtils.AddGlobalNotification("Available commands:");
foreach (IChatCommand command in commands)
{
ChatUtils.AddGlobalNotification("/" + command.Name + " (/" + command.ShortName + ") :: " + command.Description);
}
}
}
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 void Execute(string[] args)
{
string name = ((args.Length >= 1) ? args[0] : "default");
int num = BoardIO.ResolveBoard((args.Length >= 2) ? args[1] : null);
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 void Execute(string[] args)
{
string text = ((args.Length >= 1) ? args[0] : "default");
int num = BoardIO.ResolveBoard((args.Length >= 2) ? args[1] : null);
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 {Plugin.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 void Execute(string[] args)
{
if (Plugin.EnableFeature == null)
{
return;
}
int result;
if (args.Length == 0)
{
Plugin.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;
}
Plugin.chalkySize = result;
ChatUtils.AddGlobalNotification($"Chalk size is now set to {Plugin.chalkySize}.");
}
else
{
ChatUtils.AddGlobalNotification("Invalid size value. Please provide a valid integer.");
}
}
}
public class ShowChalkyCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "chalkyshowcommand";
public string Name => "chalkyshowcommand";
public string ShortName => "cshc";
public string Description
{
get
{
ConfigEntry<bool>? showCommand = Plugin.ShowCommand;
return "Toggle Chalky show/hide Chalky command in chat.If enabled, user command such as '/chalkysetcolor' 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("Chalky user command is now " + (Plugin.ShowCommand.Value ? "shown" : "hidden") + ".");
}
}
}
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 void Execute(string[] args)
{
if (Plugin.EnableFeature != null)
{
Plugin.EnableFeature.Value = !Plugin.EnableFeature.Value;
ChatUtils.AddGlobalNotification("Chalky feature is now " + (Plugin.EnableFeature.Value ? "enabled" : "disabled") + ".");
}
}
}
public class DisabledChalkySetColor
{
public const string CMD = "chalkysetcolor";
public string Name => "chalkysetcolor";
public string ShortName => "csc";
public string Description => "Set the color of the chalk. Not persistent, will reset to default on game restart. Usage: /chalkysetcolor [hex color]";
public void Execute(string[] args)
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
if (Plugin.EnableFeature != null)
{
Color value = default(Color);
if (args.Length == 0)
{
ChatUtils.AddGlobalNotification("Reset chalk color.");
Plugin.chalkyColor = null;
}
else if (!ColorUtility.TryParseHtmlString(args[0], ref value))
{
ChatUtils.AddGlobalNotification("Invalid color value. Please provide a valid hex color code (e.g. #FF0000 for red).");
}
else
{
Plugin.chalkyColor = value;
ChatUtils.AddGlobalNotification("Chalk color is now set to " + args[0] + ".");
}
}
}
}
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 chalky for Chalky commands");
}
else
{
if (!(args[0] == "chalky"))
{
return;
}
if (commands != null)
{
ChatUtils.AddGlobalNotification("Chalky Version (0.0.3).");
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);
}
}
}