Please disclose if your mod was created primarily 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 VBServerTempBan v0.1.0
VBServerTempBan.dll
Decompiled 20 hours agousing 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>(); } } }