Decompiled source of ScheduledMessages v1.5.0

plugins/ScheduledMessages.dll

Decompiled 3 months ago
using 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();
		}
	}
}