Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ScheduledMessages v1.5.0
plugins/ScheduledMessages.dll
Decompiled 3 months agousing System; using System.Collections; 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.Threading; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [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("ScheduledMessages")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+ecf8632be9bd7c7009759f58bceb43c3d43c5ecd")] [assembly: AssemblyProduct("ScheduledMessages")] [assembly: AssemblyTitle("ScheduledMessages")] [assembly: AssemblyVersion("1.0.0.0")] namespace ScheduledMessages; public class ScheduledMessage { public int Hour; public int Minute; public string Time; public string Message; } public class ScheduledMessagesConfig { public int UtcOffset; public string WelcomeMessage; public int WelcomeDelay; public List<ScheduledMessage> ScheduledMessages = new List<ScheduledMessage>(); } [BepInPlugin("com.byawn.scheduledmessages", "ScheduledMessages", "1.5.0")] public class ScheduledMessagesPlugin : BaseUnityPlugin { public const string PluginGUID = "com.byawn.scheduledmessages"; public const string PluginName = "ScheduledMessages"; public const string PluginVersion = "1.5.0"; internal static ManualLogSource Log; private Harmony harmony; private ScheduledMessagesConfig config; private readonly HashSet<string> sentThisMinute = new HashSet<string>(); private int lastCheckedMinute = -1; private readonly HashSet<long> knownPeers = new HashSet<long>(); private string configPath; private FileSystemWatcher configWatcher; private DateTime lastConfigReload = DateTime.MinValue; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; harmony = new Harmony("com.byawn.scheduledmessages"); harmony.PatchAll(); configPath = Path.Combine(Paths.ConfigPath, "scheduledmessages.cfg"); LoadConfig(); StartConfigWatcher(); Log.LogInfo((object)"ScheduledMessages v1.5.0 loaded."); } private void LoadConfig() { if (!File.Exists(configPath)) { Log.LogError((object)("Config not found at " + configPath + ". No welcome or scheduled messages will be sent.")); return; } ScheduledMessagesConfig scheduledMessagesConfig = new ScheduledMessagesConfig(); string[] array = File.ReadAllLines(configPath); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (string.IsNullOrEmpty(text) || text.StartsWith("#")) { continue; } if (text.StartsWith("timezone=")) { int.TryParse(text.Substring("timezone=".Length).Trim(), out scheduledMessagesConfig.UtcOffset); continue; } if (text.StartsWith("welcome=")) { scheduledMessagesConfig.WelcomeMessage = text.Substring("welcome=".Length).Trim(); continue; } if (text.StartsWith("welcome-delay=")) { int.TryParse(text.Substring("welcome-delay=".Length).Trim(), out scheduledMessagesConfig.WelcomeDelay); continue; } int num = text.IndexOf(' '); if (num >= 0) { string text2 = text.Substring(0, num).Trim(); string text3 = text.Substring(num + 1).Trim(); if (TryParseTime(text2, out var hour, out var minute) && !string.IsNullOrEmpty(text3)) { scheduledMessagesConfig.ScheduledMessages.Add(new ScheduledMessage { Hour = hour, Minute = minute, Time = text2, Message = text3 }); } } } config = scheduledMessagesConfig; LogConfig(); } private void LogConfig() { Log.LogInfo((object)$"Config loaded: timezone={config.UtcOffset}"); Log.LogInfo((object)("Config loaded: welcome=" + config.WelcomeMessage)); Log.LogInfo((object)$"Config loaded: welcome-delay={config.WelcomeDelay}"); foreach (ScheduledMessage scheduledMessage in config.ScheduledMessages) { Log.LogInfo((object)("Config loaded: " + scheduledMessage.Time + " " + scheduledMessage.Message)); } } private void StartConfigWatcher() { configWatcher = new FileSystemWatcher(Paths.ConfigPath, "scheduledmessages.cfg"); configWatcher.NotifyFilter = NotifyFilters.LastWrite; configWatcher.Changed += OnConfigChanged; configWatcher.EnableRaisingEvents = true; } private void OnConfigChanged(object sender, FileSystemEventArgs e) { if (!((DateTime.Now - lastConfigReload).TotalSeconds < 1.0)) { lastConfigReload = DateTime.Now; Thread.Sleep(200); Log.LogInfo((object)"Config file changed, reloading..."); LoadConfig(); } } private void Update() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } if (!string.IsNullOrEmpty(config.WelcomeMessage)) { CheckForNewPeers(); } if (!config.ScheduledMessages.Any()) { return; } DateTime dateTime = DateTime.UtcNow.AddHours(config.UtcOffset); int num = dateTime.Hour * 60 + dateTime.Minute; if (num != lastCheckedMinute) { sentThisMinute.Clear(); lastCheckedMinute = num; } foreach (ScheduledMessage scheduledMessage in config.ScheduledMessages) { int num2 = scheduledMessage.Hour * 60 + scheduledMessage.Minute; string item = scheduledMessage.Time + "|" + scheduledMessage.Message; if (num == num2 && !sentThisMinute.Contains(item)) { Broadcast(scheduledMessage.Message); sentThisMinute.Add(item); } } } private void CheckForNewPeers() { if (string.IsNullOrEmpty(config.WelcomeMessage)) { return; } List<ZNetPeer> peers = ZNet.instance.GetPeers(); foreach (ZNetPeer item in peers) { if (item.m_uid != 0L && !knownPeers.Contains(item.m_uid)) { knownPeers.Add(item.m_uid); Log.LogInfo((object)$"New peer connected: {item.m_playerName} ({item.m_uid}), sending welcome message in {config.WelcomeDelay} seconds."); ((MonoBehaviour)this).StartCoroutine(SendDelayedWelcome(item)); } } HashSet<long> currentUids = new HashSet<long>(peers.Select((ZNetPeer p) => p.m_uid)); knownPeers.RemoveWhere((long uid) => !currentUids.Contains(uid)); } private IEnumerator SendDelayedWelcome(ZNetPeer peer) { yield return (object)new WaitForSeconds((float)config.WelcomeDelay); if (peer == null) { Log.LogInfo((object)"[Welcome] no peer found to send welcome to."); yield break; } ShowMessage((MessageType)2, config.WelcomeMessage); Log.LogInfo((object)("[Welcome] Sent to " + peer.m_playerName + ": " + config.WelcomeMessage)); } private void Broadcast(string text) { if (!ZNet.instance.GetPeers().Any()) { Log.LogInfo((object)("[Scheduled] No peers connected, skipping: " + text)); return; } ShowMessage((MessageType)2, text); Log.LogInfo((object)("[Scheduled] " + text)); } private static void ShowMessage(MessageType type, string text) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected I4, but got Unknown if (!string.IsNullOrWhiteSpace(text) && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ShowMessage", new object[2] { (int)type, text }); } } private bool TryParseTime(string timeStr, out int hour, out int minute) { hour = 0; minute = 0; if (string.IsNullOrWhiteSpace(timeStr)) { return false; } string[] array = timeStr.Split(':'); if (array.Length != 2) { return false; } if (int.TryParse(array[0], out hour) && int.TryParse(array[1], out minute) && hour >= 0 && hour < 24 && minute >= 0) { return minute < 60; } return false; } private void OnDestroy() { configWatcher?.Dispose(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } }