Decompiled source of Whitelist Remove v1.0.1

plugins/WhitelistRemove.dll

Decompiled 5 days ago
using System;
using System.Collections;
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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: AssemblyFileVersion("1.0.1")]
[assembly: Guid("E74EB49A-461D-48EA-85BC-F462D60C98C4")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyProduct("WhitelistRemove")]
[assembly: AssemblyCompany("Radamanto")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("WhitelistRemove")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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 WhitelistRemove
{
	[BepInPlugin("radamanto.WhitelistRemove", "WhitelistRemove", "1.0.1")]
	public sealed class WhitelistRemovePlugin : BaseUnityPlugin
	{
		private readonly struct ParsedLine
		{
			public readonly string Raw;

			public readonly string Trimmed;

			public readonly bool IsCommentOrEmpty;

			public readonly string Token;

			public readonly bool IsNumericToken;

			public readonly ulong SteamId;

			public ParsedLine(string raw, string trimmed, bool isCommentOrEmpty, string token, bool isNumericToken, ulong steamId)
			{
				Raw = raw;
				Trimmed = trimmed;
				IsCommentOrEmpty = isCommentOrEmpty;
				Token = token;
				IsNumericToken = isNumericToken;
				SteamId = steamId;
			}
		}

		internal const string ModName = "WhitelistRemove";

		internal const string ModVersion = "1.0.1";

		internal const string Author = "radamanto";

		internal const string ModGUID = "radamanto.WhitelistRemove";

		private readonly Harmony _harmony = new Harmony("radamanto.WhitelistRemove");

		private ConfigEntry<bool> CE_Enable;

		private ConfigEntry<string> CE_WhitelistFileName;

		private ConfigEntry<float> CE_ScanIntervalSeconds;

		private ConfigEntry<float> CE_InactiveThresholdSeconds;

		private ConfigEntry<string> CE_BypassSteamIds;

		private ConfigEntry<bool> CE_BypassAdmins;

		private string _dataDir = string.Empty;

		private string _lastSeenPath = string.Empty;

		private string _removedLogPath = string.Empty;

		private string _bypassRawLast = string.Empty;

		private readonly HashSet<ulong> _bypassIds = new HashSet<ulong>();

		private void Awake()
		{
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			try
			{
				CE_Enable = ((BaseUnityPlugin)this).Config.Bind<bool>("01 - General", "Enable", true, "Enable the whitelist inactivity cleaner.");
				CE_WhitelistFileName = ((BaseUnityPlugin)this).Config.Bind<string>("02 - Whitelist", "WhitelistFileName", "permittedlist.txt", "Whitelist file name.");
				CE_ScanIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("03 - Scan", "ScanIntervalSeconds", 900f, "How often the mod scans the whitelist and removes inactive users.");
				CE_InactiveThresholdSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("03 - Scan", "InactiveThresholdSeconds", 259200f, "If a whitelisted SteamID did not log in for more than this amount of seconds, it will be removed.");
				CE_BypassSteamIds = ((BaseUnityPlugin)this).Config.Bind<string>("04 - Bypass", "BypassSteamIds", "", "SteamIDs that are NEVER removed (comma separated).");
				CE_BypassAdmins = ((BaseUnityPlugin)this).Config.Bind<bool>("04 - Bypass", "BypassAdmins", true, "If true, SteamIDs that are admins on the server are NEVER removed.");
			}
			finally
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
			((BaseUnityPlugin)this).Config.Save();
			_dataDir = Path.Combine(Paths.ConfigPath, "WhitelistRemove");
			_lastSeenPath = Path.Combine(_dataDir, "lastseen.json");
			_removedLogPath = Path.Combine(_dataDir, "removed.log");
			Directory.CreateDirectory(_dataDir);
			SeenStore.Load(_lastSeenPath, ((BaseUnityPlugin)this).Logger);
			_harmony.PatchAll(typeof(WhitelistRemovePlugin).Assembly);
			((MonoBehaviour)this).StartCoroutine(BootstrapWhenServerReady());
		}

		private IEnumerator BootstrapWhenServerReady()
		{
			while ((Object)(object)ZNet.instance == (Object)null)
			{
				yield return null;
			}
			if (CE_Enable.Value && IsServer())
			{
				yield return RunScanOnceCoroutine();
				((MonoBehaviour)this).StartCoroutine(ScanLoop());
			}
		}

		private static bool IsServer()
		{
			try
			{
				return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer();
			}
			catch
			{
				return false;
			}
		}

		private IEnumerator ScanLoop()
		{
			while (true)
			{
				float num = Mathf.Max(5f, CE_ScanIntervalSeconds.Value);
				yield return (object)new WaitForSecondsRealtime(num);
				if (CE_Enable.Value && IsServer())
				{
					yield return RunScanOnceCoroutine();
				}
			}
		}

		private void RefreshBypassCacheIfNeeded()
		{
			string text = CE_BypassSteamIds.Value ?? string.Empty;
			if (string.Equals(text, _bypassRawLast, StringComparison.Ordinal))
			{
				return;
			}
			_bypassRawLast = text;
			_bypassIds.Clear();
			string[] array = text.Split(new char[5] { ',', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length != 0 && !text2.StartsWith("//", StringComparison.Ordinal) && !text2.StartsWith("#", StringComparison.Ordinal) && !text2.StartsWith(";", StringComparison.Ordinal) && PlatformId.TryGetSteamNumber(text2, out var steamId))
				{
					_bypassIds.Add(steamId);
				}
			}
		}

		private bool IsBypassed(ulong steamId)
		{
			if (_bypassIds.Contains(steamId))
			{
				return true;
			}
			if (CE_BypassAdmins.Value)
			{
				try
				{
					if ((Object)(object)ZNet.instance != (Object)null && (ZNet.instance.IsAdmin(PlatformId.ToVanillaToken(steamId)) || ZNet.instance.IsAdmin(steamId.ToString(CultureInfo.InvariantCulture))))
					{
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		private static string FirstToken(string trimmed)
		{
			int i;
			for (i = 0; i < trimmed.Length && !char.IsWhiteSpace(trimmed[i]); i++)
			{
			}
			if (i > 0)
			{
				return trimmed.Substring(0, i);
			}
			return string.Empty;
		}

		private static string? TryGetSavedirFromCommandLine()
		{
			try
			{
				string[] commandLineArgs = Environment.GetCommandLineArgs();
				for (int i = 0; i < commandLineArgs.Length; i++)
				{
					string text = commandLineArgs[i] ?? string.Empty;
					if (string.Equals(text, "-savedir", StringComparison.OrdinalIgnoreCase))
					{
						if (i + 1 < commandLineArgs.Length)
						{
							string text2 = (commandLineArgs[i + 1] ?? string.Empty).Trim().Trim(new char[1] { '"' });
							if (!string.IsNullOrWhiteSpace(text2))
							{
								return text2;
							}
						}
						return null;
					}
					if (!text.StartsWith("-savedir", StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					int num = text.IndexOf('=');
					int num2 = text.IndexOf(':');
					int num3 = -1;
					if (num >= 0)
					{
						num3 = num;
					}
					else if (num2 >= 0)
					{
						num3 = num2;
					}
					if (num3 >= 0 && num3 + 1 < text.Length)
					{
						string text3 = text.Substring(num3 + 1).Trim().Trim(new char[1] { '"' });
						if (!string.IsNullOrWhiteSpace(text3))
						{
							return text3;
						}
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static string GetVanillaListRootPath()
		{
			string text = TryGetSavedirFromCommandLine();
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return Application.persistentDataPath;
		}

		private IEnumerator RunScanOnceCoroutine()
		{
			RefreshBypassCacheIfNeeded();
			string text = (CE_WhitelistFileName.Value ?? "permittedlist.txt").Trim();
			if (string.IsNullOrWhiteSpace(text))
			{
				yield break;
			}
			string vanillaListRootPath = GetVanillaListRootPath();
			if (string.IsNullOrWhiteSpace(vanillaListRootPath))
			{
				yield break;
			}
			Directory.CreateDirectory(vanillaListRootPath);
			string whitelistPath = Path.Combine(vanillaListRootPath, text);
			if (!File.Exists(whitelistPath))
			{
				yield break;
			}
			long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
			long threshold = (long)Mathf.Max(1f, CE_InactiveThresholdSeconds.Value);
			HashSet<ulong> online = OnlineSnapshot.GetOnlineSteamIds();
			bool onlineSeenChanged = false;
			foreach (ulong item in online)
			{
				SeenStore.SetLastSeen(item, now);
				onlineSeenChanged = true;
			}
			string[] lines = Array.Empty<string>();
			bool readOk = false;
			int readAttempt = 0;
			while (readAttempt < 3)
			{
				bool flag;
				try
				{
					lines = File.ReadAllLines(whitelistPath, Encoding.UTF8);
					readOk = true;
				}
				catch (IOException)
				{
					readAttempt++;
					if (readAttempt >= 3)
					{
						break;
					}
					flag = true;
					goto IL_016c;
				}
				catch
				{
				}
				break;
				IL_016c:
				if (flag)
				{
					yield return (object)new WaitForSecondsRealtime(0.2f);
				}
			}
			if (!readOk)
			{
				yield break;
			}
			List<ParsedLine> list = new List<ParsedLine>(lines.Length);
			for (int i = 0; i < lines.Length; i++)
			{
				string text2 = lines[i] ?? string.Empty;
				string text3 = text2.Trim();
				if (text3.Length == 0 || text3.StartsWith("//", StringComparison.Ordinal) || text3.StartsWith("#", StringComparison.Ordinal) || text3.StartsWith(";", StringComparison.Ordinal))
				{
					list.Add(new ParsedLine(text2, text3, isCommentOrEmpty: true, string.Empty, isNumericToken: false, 0uL));
					continue;
				}
				string text4 = FirstToken(text3);
				ulong steamId;
				if (text4.Length == 0)
				{
					list.Add(new ParsedLine(text2, text3, isCommentOrEmpty: true, string.Empty, isNumericToken: false, 0uL));
				}
				else if (PlatformId.TryGetSteamNumber(text4, out steamId))
				{
					list.Add(new ParsedLine(text2, text3, isCommentOrEmpty: false, text4, isNumericToken: true, steamId));
				}
				else
				{
					list.Add(new ParsedLine(text2, text3, isCommentOrEmpty: false, text4, isNumericToken: false, 0uL));
				}
			}
			if (list.Count == 0)
			{
				yield break;
			}
			bool flag2 = onlineSeenChanged;
			int num = 0;
			Dictionary<ulong, long> pendingRemoval = new Dictionary<ulong, long>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			HashSet<ulong> keptUlong = new HashSet<ulong>();
			for (int j = 0; j < list.Count; j++)
			{
				ParsedLine parsedLine = list[j];
				if (!parsedLine.IsCommentOrEmpty && parsedLine.IsNumericToken)
				{
					ulong steamId2 = parsedLine.SteamId;
					long lastSeen;
					if (online.Contains(steamId2))
					{
						hashSet.Add(parsedLine.Token);
						keptUlong.Add(steamId2);
					}
					else if (IsBypassed(steamId2))
					{
						hashSet.Add(parsedLine.Token);
						keptUlong.Add(steamId2);
					}
					else if (!SeenStore.TryGetLastSeen(steamId2, out lastSeen))
					{
						SeenStore.SetLastSeen(steamId2, now);
						flag2 = true;
						hashSet.Add(parsedLine.Token);
						keptUlong.Add(steamId2);
					}
					else if (now - lastSeen > threshold)
					{
						num++;
						pendingRemoval[steamId2] = lastSeen;
					}
					else
					{
						hashSet.Add(parsedLine.Token);
						keptUlong.Add(steamId2);
					}
				}
			}
			if (num == 0)
			{
				if (flag2)
				{
					SeenStore.Save(_lastSeenPath, ((BaseUnityPlugin)this).Logger);
				}
				yield break;
			}
			List<string> rebuilt = new List<string>(list.Count);
			for (int k = 0; k < list.Count; k++)
			{
				ParsedLine parsedLine2 = list[k];
				if (parsedLine2.IsCommentOrEmpty)
				{
					rebuilt.Add(parsedLine2.Raw);
				}
				else if (!parsedLine2.IsNumericToken)
				{
					rebuilt.Add(parsedLine2.Raw);
				}
				else if (hashSet.Contains(parsedLine2.Token))
				{
					rebuilt.Add(parsedLine2.Raw);
				}
			}
			bool writeOk = false;
			int writeAttempt = 0;
			while (writeAttempt < 3)
			{
				bool flag3;
				try
				{
					if (File.ReadAllLines(whitelistPath, Encoding.UTF8).SequenceEqual(lines))
					{
						HashSet<ulong> onlineSteamIds = OnlineSnapshot.GetOnlineSteamIds();
						if (!pendingRemoval.Keys.Any(onlineSteamIds.Contains))
						{
							FileIoRetry.AtomicWriteText(whitelistPath, string.Join(Environment.NewLine, rebuilt) + Environment.NewLine);
							writeOk = true;
						}
					}
				}
				catch (IOException)
				{
					writeAttempt++;
					if (writeAttempt >= 3)
					{
						break;
					}
					flag3 = true;
					goto IL_055e;
				}
				catch
				{
				}
				break;
				IL_055e:
				if (flag3)
				{
					yield return (object)new WaitForSecondsRealtime(0.2f);
				}
			}
			if (!writeOk)
			{
				yield break;
			}
			foreach (KeyValuePair<ulong, long> item2 in pendingRemoval)
			{
				SeenStore.Remove(item2.Key);
				AppendRemovedLog(_removedLogPath, item2.Key, item2.Value, now - item2.Value, "inactive", ((BaseUnityPlugin)this).Logger);
			}
			SeenStore.PruneTo(keptUlong);
			SeenStore.Save(_lastSeenPath, ((BaseUnityPlugin)this).Logger);
		}

		private static void AppendRemovedLog(string removedLogPath, ulong steamId, long lastSeen, long inactiveSeconds, string reason, ManualLogSource logger)
		{
			try
			{
				Directory.CreateDirectory(Path.GetDirectoryName(removedLogPath) ?? ".");
				string text = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd HH:mm:ss 'UTC'", CultureInfo.InvariantCulture);
				string text2 = DateTimeOffset.FromUnixTimeSeconds(lastSeen).ToString("yyyy-MM-dd HH:mm:ss 'UTC'", CultureInfo.InvariantCulture);
				string text3 = "[" + text + "] removed steamid=" + steamId.ToString(CultureInfo.InvariantCulture) + " reason=" + reason + " lastSeen=" + text2 + " inactiveSeconds=" + inactiveSeconds.ToString(CultureInfo.InvariantCulture);
				File.AppendAllText(removedLogPath, text3 + Environment.NewLine, Encoding.UTF8);
			}
			catch
			{
			}
		}
	}
	internal static class SeenStore
	{
		private static readonly object LockObj = new object();

		private static readonly Dictionary<ulong, long> LastSeenUnixBySteamId = new Dictionary<ulong, long>();

		private static bool _loaded;

		internal static void Load(string path, ManualLogSource logger)
		{
			lock (LockObj)
			{
				if (_loaded)
				{
					return;
				}
				_loaded = true;
				if (!File.Exists(path))
				{
					return;
				}
				try
				{
					string[] array = File.ReadAllLines(path, Encoding.UTF8);
					for (int i = 0; i < array.Length; i++)
					{
						string text = (array[i] ?? string.Empty).Trim();
						if (text.Length == 0 || text[0] != '"')
						{
							continue;
						}
						int num = text.IndexOf('"', 1);
						if (num <= 1)
						{
							continue;
						}
						string s = text.Substring(1, num - 1);
						int num2 = text.IndexOf(':', num + 1);
						if (num2 >= 0)
						{
							string s2 = text.Substring(num2 + 1).Trim().TrimEnd(new char[1] { ',' });
							if (ulong.TryParse(s, NumberStyles.None, CultureInfo.InvariantCulture, out var result) && long.TryParse(s2, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
							{
								LastSeenUnixBySteamId[result] = result2;
							}
						}
					}
				}
				catch
				{
				}
			}
		}

		internal static bool TryGetLastSeen(ulong steamId, out long lastSeen)
		{
			lock (LockObj)
			{
				return LastSeenUnixBySteamId.TryGetValue(steamId, out lastSeen);
			}
		}

		internal static void SetLastSeen(ulong steamId, long unixSeconds)
		{
			lock (LockObj)
			{
				LastSeenUnixBySteamId[steamId] = unixSeconds;
			}
		}

		internal static void MarkSeenNow(ulong steamId)
		{
			long unixSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
			SetLastSeen(steamId, unixSeconds);
		}

		internal static bool Remove(ulong steamId)
		{
			lock (LockObj)
			{
				return LastSeenUnixBySteamId.Remove(steamId);
			}
		}

		internal static int PruneTo(HashSet<ulong> keepSteamIds)
		{
			lock (LockObj)
			{
				if (LastSeenUnixBySteamId.Count == 0)
				{
					return 0;
				}
				int num = 0;
				ulong[] array = LastSeenUnixBySteamId.Keys.ToArray();
				foreach (ulong num2 in array)
				{
					if (!keepSteamIds.Contains(num2) && LastSeenUnixBySteamId.Remove(num2))
					{
						num++;
					}
				}
				return num;
			}
		}

		internal static void Save(string path, ManualLogSource logger)
		{
			lock (LockObj)
			{
				try
				{
					StringBuilder stringBuilder = new StringBuilder(4096);
					stringBuilder.AppendLine("{");
					bool flag = true;
					foreach (KeyValuePair<ulong, long> item in LastSeenUnixBySteamId.OrderBy((KeyValuePair<ulong, long> k) => k.Key))
					{
						if (!flag)
						{
							stringBuilder.AppendLine(",");
						}
						flag = false;
						stringBuilder.Append("  \"");
						stringBuilder.Append(item.Key.ToString(CultureInfo.InvariantCulture));
						stringBuilder.Append("\": ");
						stringBuilder.Append(item.Value.ToString(CultureInfo.InvariantCulture));
					}
					stringBuilder.AppendLine();
					stringBuilder.AppendLine("}");
					string content = stringBuilder.ToString();
					FileIoRetry.AtomicWriteText(path, content);
				}
				catch
				{
				}
			}
		}
	}
	internal static class PlatformId
	{
		internal static bool TryGetSteamNumber(string? value, out ulong steamId)
		{
			steamId = 0uL;
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string text = value.Trim();
			if (text.StartsWith("V_", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(2);
			}
			if (text.StartsWith("Steam_", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(6);
			}
			if (ulong.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out steamId))
			{
				return steamId != 0;
			}
			return false;
		}

		internal static string ToVanillaToken(ulong steamId)
		{
			return "V_" + steamId.ToString(CultureInfo.InvariantCulture);
		}
	}
	internal static class OnlineSnapshot
	{
		private static bool TryGetSteamId(ZNetPeer peer, out ulong steamId)
		{
			steamId = 0uL;
			try
			{
				if (peer == null)
				{
					return false;
				}
				ISocket socket = peer.m_socket;
				if (socket == null)
				{
					return false;
				}
				string text = (socket.GetHostName() ?? string.Empty).Trim();
				if (text.Length == 0)
				{
					return false;
				}
				int num = text.IndexOf(':');
				if (num >= 0)
				{
					text = text.Substring(0, num).Trim();
				}
				if (text.Length == 0)
				{
					return false;
				}
				return PlatformId.TryGetSteamNumber(text, out steamId);
			}
			catch
			{
				return false;
			}
		}

		internal static HashSet<ulong> GetOnlineSteamIds()
		{
			HashSet<ulong> hashSet = new HashSet<ulong>();
			try
			{
				if ((Object)(object)ZNet.instance == (Object)null)
				{
					return hashSet;
				}
				List<ZNetPeer> peers = ZNet.instance.GetPeers();
				for (int i = 0; i < peers.Count; i++)
				{
					ZNetPeer val = peers[i];
					if (val != null && TryGetSteamId(val, out var steamId))
					{
						hashSet.Add(steamId);
					}
				}
			}
			catch
			{
			}
			return hashSet;
		}
	}
	internal static class FileIoRetry
	{
		internal const int MaxRetries = 3;

		internal const float RetryDelaySeconds = 0.2f;

		internal static void AtomicWriteText(string path, string content)
		{
			Directory.CreateDirectory(Path.GetDirectoryName(path) ?? ".");
			string text = path + ".tmp";
			File.WriteAllText(text, content, Encoding.UTF8);
			if (File.Exists(path))
			{
				File.Replace(text, path, path + ".bak", ignoreMetadataErrors: true);
			}
			else
			{
				File.Move(text, path);
			}
		}

		private static void TryDelete(string path)
		{
			try
			{
				if (File.Exists(path))
				{
					File.Delete(path);
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch]
	internal static class PeerSeenPatches
	{
		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		[HarmonyPostfix]
		private static void ZNet_RPC_PeerInfo_Postfix(ZNet __instance, ZRpc rpc)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null || !__instance.IsServer())
				{
					return;
				}
				List<ZNetPeer> peers = __instance.GetPeers();
				for (int i = 0; i < peers.Count; i++)
				{
					ZNetPeer val = peers[i];
					if (val == null || val.m_rpc != rpc)
					{
						continue;
					}
					ISocket socket = val.m_socket;
					if (socket == null)
					{
						break;
					}
					string text = (socket.GetHostName() ?? string.Empty).Trim();
					if (text.Length != 0)
					{
						int num = text.IndexOf(':');
						if (num >= 0)
						{
							text = text.Substring(0, num).Trim();
						}
						if (PlatformId.TryGetSteamNumber(text, out var steamId))
						{
							SeenStore.MarkSeenNow(steamId);
						}
					}
					break;
				}
			}
			catch
			{
			}
		}
	}
}