Decompiled source of VBServerTempBan v0.1.0

VBServerTempBan.dll

Decompiled 20 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace VBServerTempBan
{
	public class BanEntry
	{
		public string PlayerId { get; set; }

		public DateTime UnbanTime { get; set; }

		public string Reason { get; set; }

		public bool IsExpired => DateTime.UtcNow >= UnbanTime;

		public BanEntry()
		{
		}

		public BanEntry(string playerId, DateTime unbanTime, string reason)
		{
			PlayerId = playerId;
			UnbanTime = unbanTime;
			Reason = reason;
		}
	}
	internal static class Log
	{
		private static ManualLogSource _source;

		public static void CreateInstance(ManualLogSource source)
		{
			_source = source;
		}

		public static void Info(object msg)
		{
			_source.LogInfo((object)$"[VBServerTempBan] {msg}");
		}

		public static void Message(object msg)
		{
			_source.LogMessage((object)$"[VBServerTempBan] {msg}");
		}

		public static void Debug(object msg)
		{
			_source.LogDebug((object)$"[VBServerTempBan] {msg}");
		}

		public static void Warning(object msg)
		{
			_source.LogWarning((object)$"[VBServerTempBan] {msg}");
		}

		public static void Error(object msg)
		{
			_source.LogError((object)$"[VBServerTempBan] {msg}");
		}
	}
	public class TempBanManager : MonoBehaviour
	{
		private readonly List<BanEntry> _tempBans = new List<BanEntry>();

		private string _tempBanFilePath;

		private float _checkTimer;

		private float _fileCheckTimer;

		private DateTime _lastFileWrite = DateTime.MinValue;

		private bool _znetReady;

		private static readonly string DateFormat = "yyyy-MM-dd HH:mm:ss";

		private void Awake()
		{
			Log.Message("=== TempBanManager Initializing ===");
			_tempBanFilePath = Path.Combine(Paths.ConfigPath, "VitByr/VBServerTempBan/bantime_list.txt");
			Directory.CreateDirectory(Path.GetDirectoryName(_tempBanFilePath));
			LoadTempBanFile();
			Log.Message("Temp ban file: " + _tempBanFilePath);
			Log.Message("=== Initialization Complete ===");
		}

		private void Update()
		{
			if (!_znetReady && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.m_bannedList != null)
			{
				_znetReady = true;
				Log.Message("ZNet is ready, applying active temp bans...");
				ApplyActiveTempBans();
			}
			_fileCheckTimer += Time.deltaTime;
			if (_fileCheckTimer > 5f)
			{
				_fileCheckTimer = 0f;
				CheckFileChanges();
			}
			_checkTimer += Time.deltaTime;
			if (_checkTimer > (float)VBServerTempBan.CheckIntervalSeconds.Value)
			{
				_checkTimer = 0f;
				CheckExpiredBans();
			}
		}

		private void CheckFileChanges()
		{
			try
			{
				if (!File.Exists(_tempBanFilePath))
				{
					return;
				}
				DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(_tempBanFilePath);
				if (!(lastWriteTimeUtc <= _lastFileWrite))
				{
					_lastFileWrite = lastWriteTimeUtc;
					Log.Message($"Temp ban file changed at {lastWriteTimeUtc}, reloading...");
					LoadTempBanFile();
					if (_znetReady)
					{
						ApplyActiveTempBans();
					}
				}
			}
			catch (Exception arg)
			{
				Log.Error($"Error checking temp ban file changes: {arg}");
			}
		}

		private void LoadTempBanFile()
		{
			_tempBans.Clear();
			if (!File.Exists(_tempBanFilePath))
			{
				CreateExampleFile();
				return;
			}
			try
			{
				string[] array = File.ReadAllLines(_tempBanFilePath);
				Log.Message("========== LOADING TEMP BANS ==========");
				Log.Message($"Read {array.Length} lines from file");
				string[] array2 = array;
				foreach (string text in array2)
				{
					string text2 = text.Trim();
					if (string.IsNullOrWhiteSpace(text2) || text2.StartsWith("#"))
					{
						continue;
					}
					string[] array3 = text2.Split(new char[1] { '|' });
					if (array3.Length < 2)
					{
						Log.Message("Skipping invalid line: " + text2);
						continue;
					}
					string playerId = array3[0].Trim();
					string text3 = array3[1].Trim();
					string reason = ((array3.Length >= 3) ? array3[2].Trim() : "");
					if (!DateTime.TryParseExact(text3, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result))
					{
						Log.Message("Cannot parse date '" + text3 + "'");
					}
					else
					{
						_tempBans.Add(new BanEntry(playerId, result, reason));
					}
				}
				Log.Message($"Loaded {_tempBans.Count} temp bans (active + expired)");
				Log.Message("========== LOADING COMPLETE ==========");
			}
			catch (Exception arg)
			{
				Log.Error($"Error loading temp bans: {arg}");
			}
		}

		private void CreateExampleFile()
		{
			try
			{
				List<string> contents = new List<string>
				{
					"# ===============================================================", "#  Temporary Ban List (VBServerTempBan)", "#", "#  FORMAT:", "#      SteamID64 | UnbanTimeUTC | Reason", "#", "#  TIME FORMAT (UTC ONLY):", "#      YYYY-MM-DD HH:mm:ss", "#", "#  IMPORTANT:",
					"#  - All times MUST be in UTC.", "#  - When the unban time passes, the SteamID will be automatically", "#    removed from the server's bannedlist.txt.", "#  - Permanent bans should NOT be added here — only temporary ones.", "#", "#  EXAMPLES:", "#", "#  Active ban (expires in the future):", "#      76561198000000001 | 2030-01-01 00:00:00 | Example future ban", "#",
					"#  Expired ban (will be removed on next check):", "#      76561198000000002 | 2020-01-01 00:00:00 | Old expired ban", "#", "# ===============================================================", "", "# Add your temporary bans below:", ""
				};
				File.WriteAllLines(_tempBanFilePath, contents);
				_lastFileWrite = File.GetLastWriteTimeUtc(_tempBanFilePath);
				Log.Message("Created example temp ban file at " + _tempBanFilePath);
				LoadTempBanFile();
			}
			catch (Exception arg)
			{
				Log.Error($"Error creating example temp ban file: {arg}");
			}
		}

		private void ApplyActiveTempBans()
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.m_bannedList == null)
				{
					return;
				}
				DateTime now = DateTime.UtcNow;
				List<string> list = ZNet.instance.m_bannedList.GetList();
				bool flag = false;
				foreach (BanEntry item in _tempBans.Where((BanEntry b) => b.UnbanTime > now))
				{
					if (!list.Contains(item.PlayerId))
					{
						Log.Message("Adding temp ban: " + item.PlayerId);
						ZNet.instance.m_bannedList.Add(item.PlayerId);
						flag = true;
					}
				}
				if (flag)
				{
					ZNet.instance.m_bannedList.Save();
					Log.Message("Ban list saved after applying temp bans");
				}
			}
			catch (Exception arg)
			{
				Log.Error($"Error applying temp bans: {arg}");
			}
		}

		private void CheckExpiredBans()
		{
			try
			{
				if (!_znetReady || !Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.m_bannedList == null)
				{
					return;
				}
				DateTime now = DateTime.UtcNow;
				List<string> list = ZNet.instance.m_bannedList.GetList();
				List<BanEntry> list2 = _tempBans.Where((BanEntry b) => b.UnbanTime <= now).ToList();
				if (!list2.Any())
				{
					return;
				}
				bool flag = false;
				foreach (BanEntry item in list2)
				{
					if (list.Contains(item.PlayerId))
					{
						Log.Message("Removing expired temp ban: " + item.PlayerId);
						ZNet.instance.m_bannedList.Remove(item.PlayerId);
						flag = true;
					}
					_tempBans.Remove(item);
				}
				if (flag)
				{
					ZNet.instance.m_bannedList.Save();
					Log.Message("Ban list saved after removing expired temp bans");
				}
				SaveTempBanFile();
			}
			catch (Exception arg)
			{
				Log.Error($"Error checking expired temp bans: {arg}");
			}
		}

		private void SaveTempBanFile()
		{
			try
			{
				List<string> list = new List<string>
				{
					"# ===============================================================", "#  Temporary Ban List (VBServerTempBan)", "#", "#  FORMAT:", "#      SteamID64 | UnbanTimeUTC | Reason", "#", "#  TIME FORMAT (UTC ONLY):", "#      YYYY-MM-DD HH:mm:ss", "#", "#  IMPORTANT:",
					"#  - All times MUST be in UTC.", "#  - When the unban time passes, the SteamID will be automatically", "#    removed from the server's bannedlist.txt.", "#  - Permanent bans should NOT be added here — only temporary ones.", "#", "#  EXAMPLES:", "#", "#  Active ban (expires in the future):", "#      76561198000000001 | 2030-01-01 00:00:00 | Example future ban", "#",
					"#  Expired ban (will be removed on next check):", "#      76561198000000002 | 2020-01-01 00:00:00 | Old expired ban", "#", "# ===============================================================", "", "# Add your temporary bans below:", ""
				};
				foreach (BanEntry tempBan in _tempBans)
				{
					list.Add($"{tempBan.PlayerId}|{tempBan.UnbanTime:yyyy-MM-dd HH:mm:ss}|{tempBan.Reason}");
				}
				File.WriteAllLines(_tempBanFilePath, list);
				_lastFileWrite = File.GetLastWriteTimeUtc(_tempBanFilePath);
				Log.Message($"Saved {_tempBans.Count} temp bans to bantime_list.yml");
			}
			catch (Exception arg)
			{
				Log.Error($"Error saving temp bans: {arg}");
			}
		}
	}
	[BepInPlugin("VitByr.VBServerTempBan", "VBServerTempBan", "0.1.0")]
	[BepInProcess("valheim_server.exe")]
	internal class VBServerTempBan : BaseUnityPlugin
	{
		public const string ModGUID = "VitByr.VBServerTempBan";

		public const string ModName = "VBServerTempBan";

		public const string ModVersion = "0.1.0";

		public static ConfigEntry<int> CheckIntervalSeconds;

		private static TempBanManager _banManager;

		private void Awake()
		{
			Log.CreateInstance(((BaseUnityPlugin)this).Logger);
			CheckIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Check Interval", 30, "How often to check for expired bans (seconds)");
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "VitByr.VBServerTempBan");
		}

		private void Start()
		{
			_banManager = ((Component)this).gameObject.AddComponent<TempBanManager>();
		}
	}
}