using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Remind.Core;
using Remind.Core.Commands;
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("Remind: A mod for On-Together with in-game utility commands including scheduled reminders (/remindmein, /remindlocalin, /remindglobalin), and more. Use /remindhelp")]
[assembly: AssemblyFileVersion("1.1.10.0")]
[assembly: AssemblyInformationalVersion("1.1.10+1902b86bd15c5c4d436b4d4523e47990ddeec1dd")]
[assembly: AssemblyProduct("AndrewLin.Remind")]
[assembly: AssemblyTitle("AndrewLin.Remind")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/andrewlimforfun/ot-mods")]
[assembly: AssemblyVersion("1.1.10.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 Remind
{
public static class BuildInfo
{
public const string Version = "1.1.10";
}
[BepInPlugin("com.andrewlin.ontogether.remind", "Remind", "1.1.10")]
public class RemindPlugin : BaseUnityPlugin
{
public const int OriginalNotificationLimit = 99;
public const int DefaultNotificationLimit = 300;
public const int MaxNotificationLimit = 999;
public const int DefaultChatSinkLocalRange = 5;
public const int DefaultGlobalChatMessageLimit = 50;
public const int DefaultLocalChatMessageLimit = 25;
private static readonly ConcurrentQueue<Action> _mainThreadQueue = new ConcurrentQueue<Action>();
public const string ModGUID = "com.andrewlin.ontogether.remind";
public const string ModName = "Remind";
public const string ModVersion = "1.1.10";
public static ConfigEntry<bool>? EnableFeature { get; private set; }
public static ConfigEntry<bool>? ChatConfirmation { get; private set; }
public static ConfigEntry<bool>? ShowCommand { get; private set; }
public static ScheduledTaskManager? ScheduledTaskManager { get; private set; }
public static void RunOnMainThread(Action action)
{
ConfigEntry<bool>? enableFeature = EnableFeature;
if (enableFeature != null && enableFeature.Value)
{
_mainThreadQueue.Enqueue(action);
}
}
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)"Remind v1.1.10 is loaded!");
InitConfig();
Harmony val = new Harmony("com.andrewlin.ontogether.remind");
ChatCommandManager commandManager = AlphaPlugin.CommandManager;
if (commandManager != null)
{
commandManager.Register((IChatCommand)(object)new RemindChatConfirmationCommand());
}
ChatCommandManager commandManager2 = AlphaPlugin.CommandManager;
if (commandManager2 != null)
{
commandManager2.Register((IChatCommand)(object)new RemindGlobalAtCommand());
}
ChatCommandManager commandManager3 = AlphaPlugin.CommandManager;
if (commandManager3 != null)
{
commandManager3.Register((IChatCommand)(object)new RemindGlobalInCommand());
}
ChatCommandManager commandManager4 = AlphaPlugin.CommandManager;
if (commandManager4 != null)
{
commandManager4.Register((IChatCommand)(object)new RemindLocalAtCommand());
}
ChatCommandManager commandManager5 = AlphaPlugin.CommandManager;
if (commandManager5 != null)
{
commandManager5.Register((IChatCommand)(object)new RemindLocalInCommand());
}
ChatCommandManager commandManager6 = AlphaPlugin.CommandManager;
if (commandManager6 != null)
{
commandManager6.Register((IChatCommand)(object)new RemindMeAtCommand());
}
ChatCommandManager commandManager7 = AlphaPlugin.CommandManager;
if (commandManager7 != null)
{
commandManager7.Register((IChatCommand)(object)new RemindMeInCommand());
}
ChatCommandManager commandManager8 = AlphaPlugin.CommandManager;
if (commandManager8 != null)
{
commandManager8.Register((IChatCommand)(object)new RemindToggleCommand());
}
ScheduledTaskManager = new ScheduledTaskManager();
}
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.");
ChatConfirmation = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ChatConfirmation", false, "Broadcast and confirm the creation of reminders in chat.");
}
private void Update()
{
ConfigEntry<bool>? enableFeature = EnableFeature;
if (enableFeature == null || !enableFeature.Value)
{
return;
}
Action result;
while (_mainThreadQueue.TryDequeue(out result))
{
try
{
result();
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Main thread action failed: " + ex.Message));
}
}
ScheduledTaskManager?.Tick();
}
private void OnDestroy()
{
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "AndrewLin.Remind";
public const string PLUGIN_NAME = "AndrewLin.Remind";
public const string PLUGIN_VERSION = "1.1.10";
}
}
namespace Remind.Core
{
public class ScheduledTask
{
private readonly Action _action;
public DateTime FireAt { get; }
public bool IsCancelled { get; private set; }
internal ScheduledTask(DateTime fireAt, Action action)
{
FireAt = fireAt;
_action = action;
}
public void Cancel()
{
IsCancelled = true;
}
internal void Execute()
{
_action();
}
}
public class ScheduledTaskManager
{
private readonly List<ScheduledTask> _tasks = new List<ScheduledTask>();
private readonly ManualLogSource _log = Logger.CreateLogSource("Remind.STM");
public int PendingCount => _tasks.Count;
public ScheduledTask ScheduleIn(TimeSpan delay, Action action)
{
return ScheduleAt(DateTime.UtcNow + delay, action);
}
public bool TryScheduleIn(string delay, Action action, out ScheduledTask? task, out string error)
{
TimeSpan timeSpan = default(TimeSpan);
if (TimeUtils.TryParseDuration(delay, ref timeSpan) && timeSpan > TimeSpan.Zero)
{
task = ScheduleIn(timeSpan, action);
error = "";
return true;
}
task = null;
error = "Invalid duration: '" + delay + "'. Use ISO 8601 (1h30m, 15s, PT1H30M) or hh:mm:ss.";
return false;
}
private ScheduledTask ScheduleAt(DateTime fireAt, Action action)
{
ScheduledTask scheduledTask = new ScheduledTask(fireAt, action);
_tasks.Add(scheduledTask);
return scheduledTask;
}
public bool TryScheduleAt(string fireAt, Action action, out ScheduledTask? task, out string error)
{
if (!DateTime.TryParse(fireAt, out var result))
{
task = null;
error = "Invalid time: '" + fireAt + "'. Use HH:mm, HH:mm:ss, or yyyy-MM-dd HH:mm.";
return false;
}
DateTime dateTime = ((result.Kind == DateTimeKind.Utc) ? result : result.ToUniversalTime());
if (dateTime <= DateTime.UtcNow)
{
dateTime = dateTime.AddHours(24.0);
if (dateTime <= DateTime.UtcNow)
{
task = null;
error = "Time '" + fireAt + "' is in the past.";
return false;
}
}
task = ScheduleAt(dateTime, action);
error = "";
return true;
}
public void Tick()
{
if (_tasks.Count == 0)
{
return;
}
DateTime utcNow = DateTime.UtcNow;
for (int num = _tasks.Count - 1; num >= 0; num--)
{
ScheduledTask scheduledTask = _tasks[num];
if (scheduledTask.IsCancelled || scheduledTask.FireAt <= utcNow)
{
_tasks.RemoveAt(num);
if (!scheduledTask.IsCancelled)
{
try
{
scheduledTask.Execute();
}
catch (Exception arg)
{
_log.LogError((object)$"[ScheduledTaskManager] Task threw: {arg}");
}
}
}
}
}
}
}
namespace Remind.Core.Commands
{
public class RemindChatConfirmationCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "remindchatconfirmation";
public string Name => "remindchatconfirmation";
public string ShortName => "rcc";
public string Description
{
get
{
ConfigEntry<bool>? chatConfirmation = RemindPlugin.ChatConfirmation;
return "Toggle Remind chat confirmation on/off. Currently: " + ((chatConfirmation != null && chatConfirmation.Value) ? "ON" : "OFF");
}
}
public string Namespace => "remind";
public void Execute(string[] args)
{
if (RemindPlugin.ChatConfirmation != null)
{
RemindPlugin.ChatConfirmation.Value = !RemindPlugin.ChatConfirmation.Value;
ChatUtils.AddGlobalNotification("Remind broadcast creation is now " + (RemindPlugin.ChatConfirmation.Value ? "enabled" : "disabled") + ".");
}
}
}
public class RemindGlobalAtCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "remindglobalat";
public string Name => "remindglobalat";
public string ShortName => "rga";
public string Description => "Send a global chat message at a specific time. Usage: /remindglobalat [HH:mm] [message]";
public string Namespace => "remind";
public void Execute(string[] args)
{
if (RemindPlugin.ScheduledTaskManager == null)
{
ChatUtils.AddGlobalNotification("ScheduledTaskManager is not initialized.");
return;
}
if (args.Length < 2)
{
ChatUtils.AddGlobalNotification("Usage: /remindglobalat [HH:mm] [message]");
return;
}
string message = string.Join(" ", args, 1, args.Length - 1);
if (string.IsNullOrWhiteSpace(message))
{
ChatUtils.AddGlobalNotification("Please enter a valid message.");
return;
}
string text = args[0];
string username = PlayerUtils.GetUserNameNoFormat();
if (!DateTime.TryParse(text, out var result))
{
ChatUtils.AddGlobalNotification("Invalid time format. Please use HH:mm.");
return;
}
bool isLocal = false;
DateTime dateTime = ((result.Kind == DateTimeKind.Utc) ? result : result.ToUniversalTime());
if (!RemindPlugin.ScheduledTaskManager.TryScheduleAt(text, delegate
{
ChatUtils.SendMessageAsync("Remind" + username, message, isLocal, "word", (Vector3?)null);
}, out ScheduledTask _, out string error))
{
ChatUtils.AddGlobalNotification(error);
return;
}
ChatUtils.AddGlobalNotification($"Message scheduled for {dateTime:HH:mm}UTC.");
ConfigEntry<bool>? chatConfirmation = RemindPlugin.ChatConfirmation;
if (chatConfirmation != null && chatConfirmation.Value)
{
ChatUtils.SendMessageAsync("Remind" + username, $"scheduled at {dateTime:HH:mm}UTC -> {message}", isLocal, "word", (Vector3?)null);
}
}
}
public class RemindGlobalInCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "remindglobalin";
public string Name => "remindglobalin";
public string ShortName => "rgi";
public string Description => "Send a global chat message after a delay. Usage: /remindglobalin [hh:mm:ss] [message]";
public string Namespace => "remind";
public void Execute(string[] args)
{
if (RemindPlugin.ScheduledTaskManager == null)
{
ChatUtils.AddGlobalNotification("ScheduledTaskManager is not initialized.");
return;
}
if (args.Length < 2)
{
ChatUtils.AddGlobalNotification("Usage: /remindglobalin [hh:mm:ss] [message]");
return;
}
string message = string.Join(" ", args, 1, args.Length - 1);
if (string.IsNullOrWhiteSpace(message))
{
ChatUtils.AddGlobalNotification("Please enter a valid message.");
return;
}
string text = args[0];
string username = PlayerUtils.GetUserNameNoFormat();
bool flag = false;
if (!RemindPlugin.ScheduledTaskManager.TryScheduleIn(text, delegate
{
ChatUtils.SendMessageAsync("Remind" + username, message, false, "word", (Vector3?)null);
}, out ScheduledTask _, out string error))
{
ChatUtils.AddGlobalNotification(error);
return;
}
ChatUtils.AddGlobalNotification("Message scheduled in " + text + ".");
ConfigEntry<bool>? chatConfirmation = RemindPlugin.ChatConfirmation;
if (chatConfirmation != null && chatConfirmation.Value)
{
ChatUtils.SendMessageAsync("Remind" + username, "scheduled in " + text + " -> " + message, flag, "word", (Vector3?)null);
}
}
}
public class RemindLocalAtCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "remindlocalat";
public string Name => "remindlocalat";
public string ShortName => "rla";
public string Description => "Send a local chat message at a specific time. Usage: /remindlocalat [HH:mm] [message]";
public string Namespace => "remind";
public void Execute(string[] args)
{
if (RemindPlugin.ScheduledTaskManager == null)
{
ChatUtils.AddGlobalNotification("ScheduledTaskManager is not initialized.");
return;
}
if (args.Length < 2)
{
ChatUtils.AddGlobalNotification("Usage: /remindlocalat [HH:mm] [message]");
return;
}
string message = string.Join(" ", args, 1, args.Length - 1);
if (string.IsNullOrWhiteSpace(message))
{
ChatUtils.AddGlobalNotification("Please enter a valid message.");
return;
}
string text = args[0];
string username = PlayerUtils.GetUserNameNoFormat();
if (!DateTime.TryParse(text, out var result))
{
ChatUtils.AddGlobalNotification("Invalid time format. Please use HH:mm.");
return;
}
ChatUtils.AddGlobalNotification("[remindlocalat] Reminder at " + text + ": \"" + message + "\"");
bool isLocal = true;
DateTime dateTime = ((result.Kind == DateTimeKind.Utc) ? result : result.ToUniversalTime());
if (!RemindPlugin.ScheduledTaskManager.TryScheduleAt(text, delegate
{
ChatUtils.SendMessageAsync("Remind" + username, message, isLocal, "word", (Vector3?)null);
}, out ScheduledTask _, out string error))
{
ChatUtils.AddGlobalNotification(error);
return;
}
ChatUtils.AddGlobalNotification($"Message scheduled for {dateTime:HH:mm}UTC.");
ConfigEntry<bool>? chatConfirmation = RemindPlugin.ChatConfirmation;
if (chatConfirmation != null && chatConfirmation.Value)
{
ChatUtils.SendMessageAsync("Remind" + username, $"scheduled at {dateTime:HH:mm}UTC -> {message}", isLocal, "word", (Vector3?)null);
}
}
}
public class RemindLocalInCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "remindlocalin";
public string Name => "remindlocalin";
public string ShortName => "rli";
public string Description => "Send a local chat message after a delay. Usage: /remindlocalin [hh:mm:ss] [message]";
public string Namespace => "remind";
public void Execute(string[] args)
{
if (RemindPlugin.ScheduledTaskManager == null)
{
ChatUtils.AddGlobalNotification("ScheduledTaskManager is not initialized.");
return;
}
if (args.Length < 2)
{
ChatUtils.AddGlobalNotification("Usage: /remindlocalin [hh:mm:ss] [message]");
return;
}
string message = string.Join(" ", args, 1, args.Length - 1);
if (string.IsNullOrWhiteSpace(message))
{
ChatUtils.AddGlobalNotification("Please enter a valid message.");
return;
}
string text = args[0];
string username = PlayerUtils.GetUserNameNoFormat();
bool flag = true;
if (!RemindPlugin.ScheduledTaskManager.TryScheduleIn(text, delegate
{
ChatUtils.SendMessageAsync("Remind" + username, message, false, "word", (Vector3?)null);
}, out ScheduledTask _, out string error))
{
ChatUtils.AddGlobalNotification(error);
return;
}
ChatUtils.AddGlobalNotification("Message scheduled in " + text + ".");
ConfigEntry<bool>? chatConfirmation = RemindPlugin.ChatConfirmation;
if (chatConfirmation != null && chatConfirmation.Value)
{
ChatUtils.SendMessageAsync("Remind" + username, "scheduled in " + text + " -> " + message, flag, "word", (Vector3?)null);
}
}
}
public class RemindMeAtCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "remindmeat";
public string Name => "remindmeat";
public string ShortName => "rma";
public string Description => "Show a private notification at a specific time. Usage: /remindmeat [HH:mm] [message]";
public string Namespace => "remind";
public void Execute(string[] args)
{
if (RemindPlugin.ScheduledTaskManager == null)
{
ChatUtils.AddGlobalNotification("ScheduledTaskManager is not initialized.");
return;
}
if (args.Length < 2)
{
ChatUtils.AddGlobalNotification("Usage: /remindmeat [HH:mm] [message]");
return;
}
string message = string.Join(" ", args, 1, args.Length - 1);
if (string.IsNullOrWhiteSpace(message))
{
ChatUtils.AddGlobalNotification("Please enter a valid message.");
return;
}
if (!RemindPlugin.ScheduledTaskManager.TryScheduleAt(args[0], delegate
{
ChatUtils.AddGlobalNotification(message);
}, out ScheduledTask _, out string error))
{
ChatUtils.AddGlobalNotification(error);
return;
}
ChatUtils.AddGlobalNotification("[remindmeat] Reminder at " + args[0] + ": \"" + message + "\"");
}
}
public class RemindMeInCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "remindmein";
public string Name => "remindmein";
public string ShortName => "rmi";
public string Description => "Show a private notification after a delay. Usage: /remindmein [hh:mm:ss] [message]";
public string Namespace => "remind";
public void Execute(string[] args)
{
if (RemindPlugin.ScheduledTaskManager == null)
{
ChatUtils.AddGlobalNotification("ScheduledTaskManager is not initialized.");
return;
}
if (args.Length < 2)
{
ChatUtils.AddGlobalNotification("Usage: /remindmein [hh:mm:ss] [message]");
return;
}
string message = string.Join(" ", args, 1, args.Length - 1);
if (string.IsNullOrWhiteSpace(message))
{
ChatUtils.AddGlobalNotification("Please enter a valid message.");
return;
}
string text = args[0];
if (!RemindPlugin.ScheduledTaskManager.TryScheduleIn(text, delegate
{
ChatUtils.AddGlobalNotification(message);
}, out ScheduledTask _, out string error))
{
ChatUtils.AddGlobalNotification(error);
return;
}
ChatUtils.AddGlobalNotification("[remindmein] Reminder in " + text + ": \"" + message + "\"");
}
}
public class RemindToggleCommand : IChatCommand, IComparable<IChatCommand>
{
public const string CMD = "remindtoggle";
public string Name => "remindtoggle";
public string ShortName => "rt";
public string Description => "Toggle Remind feature on/off. ";
public string Namespace => "remind";
public void Execute(string[] args)
{
if (RemindPlugin.EnableFeature != null)
{
RemindPlugin.EnableFeature.Value = !RemindPlugin.EnableFeature.Value;
ChatUtils.AddGlobalNotification("Remind feature is now " + (RemindPlugin.EnableFeature.Value ? "enabled" : "disabled") + ".");
}
}
}
}