Decompiled source of VBNetTweaks v0.3.0

VBNetTweaks.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using VBNetTweaks.Patches;
using VBNetTweaks.Utils;
using VBNetTweaks.ZDOUtills;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("VBNetTweaks")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("VBNetTweaks")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d9c87954-ce20-459d-81ec-96599caed427")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.9.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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 VBNetTweaks
{
	[HarmonyPatch]
	public static class ShipSyncSystem
	{
		private class ShipData
		{
			public Vector3 pos;

			public Quaternion rot;

			public Vector3 vel;

			public float t;

			public bool ok;

			public long lastOwner;

			public float lastUpdateTime;
		}

		private class PlayerShipState
		{
			public Ship ship;

			public Vector3 localPos;

			public Quaternion localRot;

			public float lastUpdate;
		}

		private static readonly Dictionary<long, ShipData> _shipData;

		private static readonly Dictionary<long, PlayerShipState> _playerStates;

		private static readonly Dictionary<ZDOID, int> _playersOnShip;

		private static readonly Dictionary<long, ZDOID> _playerShipMap;

		private const float SMOOTH_POS_ON_SHIP = 0.35f;

		private const float SMOOTH_ROT_ON_SHIP = 0.25f;

		private const float SMOOTH_POS_OFF_SHIP = 0.25f;

		private const float SMOOTH_ROT_OFF_SHIP = 0.15f;

		private const float CORRECTION_THRESHOLD = 0.5f;

		private const float ROT_CORRECTION_THRESHOLD = 10f;

		private const string RPC_SYNC_SHIP = "VBNT.SyncShip";

		static ShipSyncSystem()
		{
			_shipData = new Dictionary<long, ShipData>();
			_playerStates = new Dictionary<long, PlayerShipState>();
			_playersOnShip = new Dictionary<ZDOID, int>();
			_playerShipMap = new Dictionary<long, ZDOID>();
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.Register<long, ZDOID>("VBNT.SyncShip", (Action<long, long, ZDOID>)RPC_SyncShip);
			}
		}

		private static void SyncShip(long playerId, ZDOID shipId)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZRoutedRpc.instance != null && playerId != 0)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "VBNT.SyncShip", new object[2] { playerId, shipId });
				PlayerCache.UpdatePlayerState(playerId, PlayerCache.IsPlayerAttached(playerId), shipId);
			}
		}

		private static void RPC_SyncShip(long sender, long playerId, ZDOID shipId)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (sender != ZNet.GetUID())
			{
				PlayerCache.UpdatePlayerState(playerId, PlayerCache.IsPlayerAttached(playerId), shipId);
			}
		}

		public static void CleanupPeer(long uid)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			lock (_shipData)
			{
				_shipData.Remove(uid);
			}
			lock (_playerStates)
			{
				if (_playerShipMap.TryGetValue(uid, out var value))
				{
					if (_playersOnShip.TryGetValue(value, out var value2))
					{
						if (value2 <= 1)
						{
							_playersOnShip.Remove(value);
						}
						else
						{
							_playersOnShip[value] = value2 - 1;
						}
					}
					_playerShipMap.Remove(uid);
				}
				_playerStates.Remove(uid);
			}
			PlayerCache.RemovePlayer(uid);
		}

		private static Ship GetShipUnderPlayer(Player p)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)p == (Object)null)
			{
				return null;
			}
			Vector3 val = ((Component)p).transform.position + Vector3.up * 0.2f;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(val, Vector3.down, ref val2, 2f))
			{
				return ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Ship>();
			}
			return null;
		}

		[HarmonyPatch(typeof(ZNetView), "Deserialize")]
		[HarmonyPostfix]
		public static void CaptureShipState(ZNetView __instance)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			if (Helper.IsServer() || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			Ship component = ((Component)__instance).GetComponent<Ship>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			ZDO zDO = __instance.GetZDO();
			if (zDO == null || !zDO.IsValid())
			{
				return;
			}
			long owner = zDO.GetOwner();
			if (owner == 0L || owner == ZNet.GetUID())
			{
				return;
			}
			Vector3 position = zDO.GetPosition();
			Quaternion rotation = zDO.GetRotation();
			float time = Time.time;
			if (!_shipData.TryGetValue(owner, out var value))
			{
				value = new ShipData
				{
					pos = position,
					rot = rotation,
					t = time,
					ok = true,
					lastOwner = owner,
					lastUpdateTime = time
				};
				_shipData[owner] = value;
				return;
			}
			if (value.lastOwner != owner)
			{
				value.vel = Vector3.zero;
				value.lastOwner = owner;
				value.lastUpdateTime = time;
			}
			float num = time - value.t;
			if (num > 0.01f && num < 0.5f)
			{
				Vector3 val = (position - value.pos) / num;
				value.vel = Vector3.Lerp(value.vel, val, 0.3f);
			}
			else if (num >= 0.5f)
			{
				value.vel = Vector3.zero;
			}
			value.pos = position;
			value.rot = rotation;
			value.t = time;
			value.ok = true;
		}

		[HarmonyPatch(typeof(Ship), "CustomFixedUpdate")]
		[HarmonyPostfix]
		public static void SmoothShip(Ship __instance)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			if (Helper.IsServer())
			{
				return;
			}
			ZNetView nview = __instance.m_nview;
			ZDO val = ((nview != null) ? nview.GetZDO() : null);
			if (val == null)
			{
				return;
			}
			long owner = val.GetOwner();
			if (owner == 0L || owner == ZNet.GetUID() || !_shipData.TryGetValue(owner, out var value) || !value.ok)
			{
				return;
			}
			Transform transform = ((Component)__instance).transform;
			float time = Time.time;
			float num = Mathf.Min(Time.deltaTime, 0.033f);
			Vector3 val2 = value.pos + value.vel * num;
			Vector3 val3 = val2 - transform.position;
			if (((Vector3)(ref val3)).magnitude > 5f)
			{
				val2 = transform.position + ((Vector3)(ref val3)).normalized * 5f;
			}
			Player localPlayer = Player.m_localPlayer;
			bool flag = PlayerCache.IsPlayerOnShip((localPlayer != null) ? localPlayer.GetPlayerID() : 0);
			float num2 = (flag ? 0.35f : 0.25f);
			float num3 = (flag ? 0.25f : 0.15f);
			float num4 = Vector3.Distance(transform.position, val2);
			if (num4 > 0.5f)
			{
				transform.position = val2;
				transform.rotation = value.rot;
				return;
			}
			float num5 = Quaternion.Angle(transform.rotation, value.rot);
			if (num5 > 10f)
			{
				transform.rotation = value.rot;
			}
			else
			{
				transform.rotation = Quaternion.Slerp(transform.rotation, value.rot, num3);
			}
			transform.position = Vector3.Lerp(transform.position, val2, num2);
		}

		[HarmonyPatch(typeof(Player), "Update")]
		[HarmonyPostfix]
		public static void TrackLocalPlayer(Player __instance)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			long playerID = __instance.GetPlayerID();
			PlayerShipState value;
			Ship val = (_playerStates.TryGetValue(playerID, out value) ? value.ship : null);
			Ship shipUnderPlayer = GetShipUnderPlayer(__instance);
			if ((Object)(object)val == (Object)(object)shipUnderPlayer && Object.op_Implicit((Object)(object)shipUnderPlayer))
			{
				if (_playerStates.TryGetValue(playerID, out var value2))
				{
					value2.localPos = ((Component)shipUnderPlayer).transform.InverseTransformPoint(((Component)__instance).transform.position);
					value2.localRot = Quaternion.Inverse(((Component)shipUnderPlayer).transform.rotation) * ((Component)__instance).transform.rotation;
					value2.lastUpdate = Time.time;
				}
				return;
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				ZNetView nview = val.m_nview;
				ZDO val2 = ((nview != null) ? nview.GetZDO() : null);
				if (val2 != null)
				{
					ZDOID uid = val2.m_uid;
					if (_playersOnShip.TryGetValue(uid, out var value3))
					{
						if (value3 <= 1)
						{
							_playersOnShip.Remove(uid);
						}
						else
						{
							_playersOnShip[uid] = value3 - 1;
						}
					}
				}
			}
			if (Object.op_Implicit((Object)(object)shipUnderPlayer))
			{
				ZNetView nview2 = shipUnderPlayer.m_nview;
				ZDO val3 = ((nview2 != null) ? nview2.GetZDO() : null);
				if (val3 != null)
				{
					ZDOID uid2 = val3.m_uid;
					_playersOnShip[uid2] = ((!_playersOnShip.TryGetValue(uid2, out var value4)) ? 1 : (value4 + 1));
					_playerShipMap[playerID] = uid2;
				}
			}
			if (!_playerStates.TryGetValue(playerID, out var value5))
			{
				value5 = new PlayerShipState();
				_playerStates[playerID] = value5;
			}
			value5.ship = shipUnderPlayer;
			if (Object.op_Implicit((Object)(object)shipUnderPlayer))
			{
				value5.localPos = ((Component)shipUnderPlayer).transform.InverseTransformPoint(((Component)__instance).transform.position);
				value5.localRot = Quaternion.Inverse(((Component)shipUnderPlayer).transform.rotation) * ((Component)__instance).transform.rotation;
			}
			value5.lastUpdate = Time.time;
			if ((Object)(object)val != (Object)(object)shipUnderPlayer)
			{
				ZDOID? obj;
				if (shipUnderPlayer == null)
				{
					obj = null;
				}
				else
				{
					ZNetView nview3 = shipUnderPlayer.m_nview;
					obj = ((nview3 == null) ? null : nview3.GetZDO()?.m_uid);
				}
				ZDOID? val4 = obj;
				ZDOID valueOrDefault = val4.GetValueOrDefault();
				SyncShip(playerID, valueOrDefault);
			}
		}

		[HarmonyPatch(typeof(Player), "LateUpdate")]
		[HarmonyPostfix]
		public static void LateUpdate_PlayerSync(Player __instance)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance == (Object)(object)Player.m_localPlayer))
			{
				long playerID = __instance.GetPlayerID();
				if (_playerStates.TryGetValue(playerID, out var value) && !((Object)(object)value.ship == (Object)null) && !((Character)__instance).IsAttached())
				{
					float num = 20f;
					Vector3 val = ((Component)value.ship).transform.TransformPoint(value.localPos);
					Quaternion val2 = ((Component)value.ship).transform.rotation * value.localRot;
					((Component)__instance).transform.position = Vector3.Lerp(((Component)__instance).transform.position, val, Time.deltaTime * num);
					((Component)__instance).transform.rotation = Quaternion.Slerp(((Component)__instance).transform.rotation, val2, Time.deltaTime * num);
				}
			}
		}
	}
	[BepInPlugin("VitByr.VBNetTweaks", "VBNetTweaks", "0.3.0")]
	[BepInIncompatibility("CacoFFF.valheim.LeanNet")]
	[BepInIncompatibility("redseiko.valheim.scenic")]
	[BepInIncompatibility("Searica.Valheim.NetworkTweaks")]
	[BepInIncompatibility("Searica.Valheim.OpenSesame")]
	[BepInIncompatibility("org.bepinex.plugins.network")]
	[BepInIncompatibility("CW_Jesse.BetterNetworking")]
	[BepInIncompatibility("com.Fire.FiresGhettoNetworkMod")]
	public class VBNetTweaks : BaseUnityPlugin
	{
		private const string ModName = "VBNetTweaks";

		private const string ModVersion = "0.3.0";

		private const string ModGUID = "VitByr.VBNetTweaks";

		public CustomRPC _configSyncRPC;

		private ConfigFile _serverConfig;

		public static ConfigEntry<bool> ModEnabled;

		public static ConfigEntry<bool> DebugEnabled;

		public static ConfigEntry<bool> VerboseLogging;

		public static ConfigEntry<bool> ModuleSteamOptimizations;

		public static ConfigEntry<bool> ModuleShipSync;

		public static ConfigEntry<int> SteamSendRateMaxKB;

		public static ConfigEntry<int> SteamSendBufferSizeKB;

		public static ConfigEntry<float> SendInterval;

		public static ConfigEntry<int> PeersPerUpdate;

		public static ConfigEntry<int> ZDOQueueLimit;

		private Harmony _harmony;

		public static VBNetTweaks Instance { get; private set; }

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_00ad: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			_serverConfig = new ConfigFile(Path.Combine(Paths.ConfigPath, "VitByr/VBNetTweaks/ServerConfig.cfg"), true);
			SynchronizationManager.Instance.RegisterCustomConfig(_serverConfig);
			Instance = this;
			ModEnabled = ConfigFileExtensions.BindConfig<bool>(_serverConfig, "00 - Master", "ModEnabled", true, "Полностью включить/выключить мод VBNetTweaks", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			if (ModEnabled.Value)
			{
				InitClientConfigs();
				InitServerConfigs();
				_configSyncRPC = NetworkManager.Instance.AddRPC("VBNetTweaks_ConfigSync", new CoroutineHandler(OnAdminConfigSync), new CoroutineHandler(OnClientConfigSync));
				SynchronizationManager.Instance.AddInitialSynchronization(_configSyncRPC, (Func<ZPackage>)(() => BuildConfigPackage()));
				CreateConfigWatcher();
				_harmony = new Harmony("VitByr.VBNetTweaks");
				if (ModuleSteamOptimizations.Value)
				{
					_harmony.PatchAll(typeof(ZSteamSocket_Patchs));
				}
				if (ModuleShipSync.Value)
				{
					_harmony.PatchAll(typeof(ShipSyncSystem));
				}
				_harmony.PatchAll(typeof(PlayerCache));
				_harmony.PatchAll(typeof(ZNet_Paths));
				_harmony.PatchAll(typeof(NetworkSyncPatches));
				_harmony.PatchAll(typeof(ZDONetworkOptimizer));
				((BaseUnityPlugin)this).Logger.LogInfo((object)"VBNetTweaks загружен!");
				if (DebugEnabled.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Режим отладки включен");
				}
			}
		}

		private void InitClientConfigs()
		{
			string text = "01 - Debug";
			DebugEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>(text, "DebugEnabled", false, "Включить отладочный вывод");
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>(text, "VerboseLogging", false, "Включить подробное логирование");
		}

		private void InitServerConfigs()
		{
			string text = "02 - Modules";
			ModuleSteamOptimizations = ConfigFileExtensions.BindConfig<bool>(_serverConfig, text, "SteamOptimizations", true, "Оптимизации Steam сокета", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ModuleShipSync = ConfigFileExtensions.BindConfig<bool>(_serverConfig, text, "ShipSync", true, "Синхронизация кораблей", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text2 = "04 - Steam Settings";
			ConfigFile serverConfig = _serverConfig;
			AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(256, 10240);
			SteamSendRateMaxKB = ConfigFileExtensions.BindConfig<int>(serverConfig, text2, "MaxRateKB", 4096, "Максимальная скорость отправки Steam (vanilla = 150 KB/s)", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ConfigFile serverConfig2 = _serverConfig;
			val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(512, 8192);
			SteamSendBufferSizeKB = ConfigFileExtensions.BindConfig<int>(serverConfig2, text2, "SendBufferSizeKB", 2048, "Размер буфера отправки Steam в KB (vanilla = ~260KB). Рекомендуется 1024-4096", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text3 = "05 - Server Settings";
			ConfigFile serverConfig3 = _serverConfig;
			val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f);
			SendInterval = ConfigFileExtensions.BindConfig<float>(serverConfig3, text3, "SendInterval", 0.03f, "Интервал отправки данных (vanilla = 0.05)", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ConfigFile serverConfig4 = _serverConfig;
			val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200);
			PeersPerUpdate = ConfigFileExtensions.BindConfig<int>(serverConfig4, text3, "PeersPerUpdate", 30, "Количество пиров за один апдейт (vanilla = 1)", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ZDOQueueLimit = ConfigFileExtensions.BindConfig<int>(_serverConfig, text3, "ZDOQueueLimit", 20480, "Размер буфера отправки ZDO пакетов (vanilla = 10240 Kb)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		}

		public ZPackage BuildConfigPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			try
			{
				val.Write(ModEnabled.Value);
				val.Write(ModuleSteamOptimizations.Value);
				val.Write(ModuleShipSync.Value);
				val.Write(SendInterval.Value);
				val.Write(PeersPerUpdate.Value);
				val.Write(ZDOQueueLimit.Value);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[VBNetTweaks] Error building config package: " + ex.Message));
				return new ZPackage();
			}
			return val;
		}

		private void ApplyConfigFromPackage(ZPackage pkg)
		{
			if (pkg == null || pkg.GetArray().Length == 0)
			{
				Debug.LogWarning((object)"[VBNetTweaks] Received empty config package");
				return;
			}
			try
			{
				pkg.SetPos(0);
				ModEnabled.Value = pkg.ReadBool();
				ModuleSteamOptimizations.Value = pkg.ReadBool();
				ModuleShipSync.Value = pkg.ReadBool();
				SendInterval.Value = pkg.ReadSingle();
				PeersPerUpdate.Value = pkg.ReadInt();
				ZDOQueueLimit.Value = pkg.ReadInt();
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[VBNetTweaks] Error applying config package: " + ex.Message));
			}
		}

		private IEnumerator OnAdminConfigSync(long sender, ZPackage pkg)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
			{
				yield break;
			}
			ZPackage serverConfigPkg = BuildConfigPackage();
			byte[] data = serverConfigPkg.GetArray();
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				ZPackage copyPkg = new ZPackage(data);
				_configSyncRPC.SendPackage(new List<ZNetPeer> { peer }, copyPkg);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBNetTweaks] Server config broadcast to all clients");
		}

		public IEnumerator OnClientConfigSync(long sender, ZPackage pkg)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"[VBNetTweaks] Клиент получил конфиг от сервера {sender}");
			ApplyConfigFromPackage(pkg);
			ConfigFileExtensions.SetSaveOnConfigSet(_serverConfig, true);
			_serverConfig.Save();
			yield break;
		}

		private void CreateConfigWatcher()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			ConfigFileWatcher val = new ConfigFileWatcher(_serverConfig, 1000L);
			val.OnConfigFileReloaded += delegate
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
				{
					Debug.Log((object)"[VBNetTweaks] Server config changed, broadcasting to all clients");
					((MonoBehaviour)this).StartCoroutine(ApplyServerConfigChanges());
				}
			};
		}

		public IEnumerator ApplyServerConfigChanges()
		{
			yield return null;
			ZPackage pkg = BuildConfigPackage();
			if (pkg.GetArray().Length != 0)
			{
				byte[] data = pkg.GetArray();
				foreach (ZNetPeer peer in ZNet.instance.GetPeers())
				{
					ZPackage copyPkg = new ZPackage(data);
					_configSyncRPC.SendPackage(new List<ZNetPeer> { peer }, copyPkg);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBNetTweaks] Server config broadcast to all clients");
			}
			if (SendInterval.Value <= 0.001f)
			{
				SendInterval.Value = 0.03f;
			}
			if (PeersPerUpdate.Value <= 0)
			{
				PeersPerUpdate.Value = 30;
			}
		}

		private void OnDestroy()
		{
			_serverConfig.Save();
			_harmony.UnpatchSelf();
		}
	}
}
namespace VBNetTweaks.ZDOUtills
{
	[HarmonyPatch]
	public static class ZDONetworkOptimizer
	{
		public static class NetworkMetrics
		{
			public static int ZdosSent { get; private set; }

			public static int ZdosReceived { get; private set; }

			public static void RecordZdoSent()
			{
				ZdosSent++;
			}

			public static void RecordZdoReceived()
			{
				ZdosReceived++;
			}
		}

		public static void OptimizedSendZDOToPeers(ZDOMan zdoManager, float dt)
		{
			try
			{
				int count = zdoManager.m_peers.Count;
				if (count <= 0)
				{
					return;
				}
				ZDOMan obj = zdoManager;
				obj.m_sendTimer += dt;
				float num = VBNetTweaks.SendInterval?.Value ?? 0.05f;
				if (zdoManager.m_sendTimer < num)
				{
					return;
				}
				zdoManager.m_sendTimer = 0f;
				int num2 = Mathf.Max(zdoManager.m_nextSendPeer, 0);
				int num3 = VBNetTweaks.PeersPerUpdate?.Value ?? 40;
				int num4 = 0;
				for (int i = 0; i < Mathf.Min(num3, count); i++)
				{
					int index = (num2 + i) % count;
					ZDOPeer peer = zdoManager.m_peers[index];
					ZDOPeer obj2 = peer;
					if (obj2 == null)
					{
						continue;
					}
					ZNetPeer peer2 = obj2.m_peer;
					bool? obj3;
					if (peer2 == null)
					{
						obj3 = null;
					}
					else
					{
						ISocket socket = peer2.m_socket;
						obj3 = ((socket != null) ? new bool?(socket.IsConnected()) : null);
					}
					if (obj3 == true)
					{
						PerformanceMonitor.Track("SendZDOs", delegate
						{
							zdoManager.SendZDOs(peer, false);
							NetworkMetrics.RecordZdoSent();
						});
						num4++;
					}
				}
				zdoManager.m_nextSendPeer = (num2 + num4) % count;
			}
			catch (Exception ex)
			{
				ZLog.LogError((object)("[VBNetTweaks] ERROR in OptimizedSendZDOToPeers: " + ex.Message));
				zdoManager.SendZDOToPeers2(dt);
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ZDOMan), "Update")]
		private static IEnumerable<CodeInstruction> ZDOManUpdateTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).Start();
			val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(ZDOMan), "SendZDOToPeers2", (Type[])null, (Type[])null), (string)null)
			});
			if (val.IsInvalid)
			{
				ZLog.LogError((object)"WARNING: SendZDOToPeers2 not found");
				return instructions;
			}
			val.SetOperandAndAdvance((object)AccessTools.Method(typeof(ZDONetworkOptimizer), "OptimizedSendZDOToPeers", (Type[])null, (Type[])null));
			return val.InstructionEnumeration();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZNetScene), "RemoveObjects")]
		private static bool RemoveObjectsPrefix(ZNetScene __instance, List<ZDO> currentNearObjects, List<ZDO> currentDistantObjects)
		{
			if (!Object.op_Implicit((Object)(object)__instance) || __instance.m_instances == null || __instance.m_tempRemoved == null)
			{
				return true;
			}
			try
			{
				PerformanceMonitor.Track("PrepareRemoval", delegate
				{
					ZDORemoval.PrepareRemovalList(__instance, currentNearObjects, currentDistantObjects);
				});
				return true;
			}
			catch (Exception ex)
			{
				ZLog.LogError((object)("[VBNetTweaks] Error in RemoveObjectsPrefix: " + ex.Message));
				return true;
			}
		}
	}
	public class ZDORemoval
	{
		public static void PrepareRemovalList(ZNetScene scene, List<ZDO> near, List<ZDO> distant)
		{
			if (!Object.op_Implicit((Object)(object)scene))
			{
				return;
			}
			byte b = (byte)((uint)Time.frameCount & 0xFFu);
			if (near != null)
			{
				foreach (ZDO item in near)
				{
					if (item != null)
					{
						item.TempRemoveEarmark = b;
					}
				}
			}
			if (distant != null)
			{
				foreach (ZDO item2 in distant)
				{
					if (item2 != null)
					{
						item2.TempRemoveEarmark = b;
					}
				}
			}
			Dictionary<ZDO, ZNetView> instances = scene.m_instances;
			List<ZNetView> tempRemoved = scene.m_tempRemoved;
			tempRemoved.Clear();
			foreach (KeyValuePair<ZDO, ZNetView> item3 in instances)
			{
				ZDO key = item3.Key;
				ZNetView value = item3.Value;
				if (key != null && Object.op_Implicit((Object)(object)value) && key.TempRemoveEarmark != b)
				{
					tempRemoved.Add(value);
				}
			}
		}
	}
}
namespace VBNetTweaks.Patches
{
	[HarmonyPatch]
	public static class NetworkSyncPatches
	{
		private const float SmoothPos = 0.22f;

		private const float SmoothRot = 0.45f;

		private const float MicroThreshold = 0.004f;

		private static bool _loggedSettings;

		private static float _teleportBoostEnd;

		public static void TriggerTeleportWindow()
		{
			_teleportBoostEnd = Time.time + 5f;
		}

		[HarmonyPatch(typeof(ZDOMan), "Update")]
		[HarmonyPostfix]
		private static void LogNetworkSettingsOnce()
		{
			if (!_loggedSettings && Object.op_Implicit((Object)(object)ZNet.instance))
			{
				_loggedSettings = true;
				float num = VBNetTweaks.SendInterval?.Value ?? 0.05f;
				int num2 = VBNetTweaks.PeersPerUpdate?.Value ?? 20;
				Helper.LogVerbose($"[VBNetTweaks] Network Config Applied -> SendInterval: {num:F3}s ({1f / num:F1}Hz) | PeersPerUpdate: {num2}");
			}
		}

		[HarmonyPatch(typeof(ZSyncTransform), "SyncPosition")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> SyncPosition_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_R4)
				{
					float num = (float)list[i].operand;
					if (Mathf.Approximately(num, 0.2f))
					{
						list[i].operand = 0.22f;
					}
					else if (Mathf.Approximately(num, 0.5f))
					{
						list[i].operand = 0.45f;
					}
					else if (Mathf.Approximately(num, 0.001f))
					{
						list[i].operand = 0.004f;
					}
				}
			}
			return list;
		}

		[HarmonyPatch(typeof(ZSyncTransform), "ClientSync")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> ClientSync_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_R4)
				{
					float num = (float)list[i].operand;
					if (Mathf.Approximately(num, 0.2f))
					{
						list[i].operand = 0.22f;
					}
					else if (Mathf.Approximately(num, 0.001f))
					{
						list[i].operand = 0.004f;
					}
					else if (Mathf.Approximately(num, 0.01f))
					{
						list[i].operand = 0.005f;
					}
				}
			}
			return list;
		}

		[HarmonyPatch(typeof(ZDOMan), "SendZDOs")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> SendZDOs_QueueLimitFix(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_I4 && (int)list[i].operand == 10240)
				{
					list[i].operand = VBNetTweaks.ZDOQueueLimit.Value;
					num++;
				}
			}
			if (num < 2)
			{
				ZLog.LogWarning((object)"[VBNetTweaks] ZDOQueueLimit patch failed: found less than 2 instances of 10240!");
			}
			else if (num == 2)
			{
				ZLog.LogWarning((object)$"[VBNetTweaks] ZDOQueueLimit patch to: {VBNetTweaks.ZDOQueueLimit.Value}");
			}
			return list;
		}

		[HarmonyPatch(typeof(ZSyncTransform), "OwnerSync")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> OwnerSync_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_R4 && Mathf.Approximately((float)list[i].operand, 0.001f))
				{
					list[i].operand = 0.004f;
				}
			}
			return list;
		}

		[HarmonyPatch(typeof(ZNetScene), "InLoadingScreen")]
		[HarmonyPrefix]
		public static bool InLoadingScreen_Extend(ref bool __result)
		{
			if (Time.time < _teleportBoostEnd)
			{
				__result = true;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ZNetScene), "CreateDestroyObjects")]
		[HarmonyPostfix]
		public static void CreateDestroyObjects_TriggerTeleport()
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null && ((Character)localPlayer).IsTeleporting())
			{
				TriggerTeleportWindow();
			}
		}
	}
	[HarmonyPatch]
	public static class ZSteamSocket_Patchs
	{
		private static bool _steamConfigApplied;

		private static float _lastApplyTime;

		private const float REAPPLY_INTERVAL = 30f;

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")]
		private static IEnumerable<CodeInstruction> RegisterGlobalCallbacks_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			if (!VBNetTweaks.ModuleSteamOptimizations.Value)
			{
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			bool flag = false;
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_I4 && (int)list[i].operand == 153600)
				{
					int num = Math.Max(64, VBNetTweaks.SteamSendRateMaxKB.Value) * 1024;
					list[i].operand = num;
					flag = true;
					ZLog.LogWarning((object)$"[VBNetTweaks] Steam rate patched: 153600 -> {num} bytes/s ({VBNetTweaks.SteamSendRateMaxKB.Value}KB/s)");
					break;
				}
			}
			if (!flag)
			{
				ZLog.LogWarning((object)"[VBNetTweaks] Steam rate constant 153600 not found in IL!");
			}
			return list;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")]
		private static void ApplySteamBuffersViaReflection()
		{
			if (!VBNetTweaks.ModuleSteamOptimizations.Value || (Time.time - _lastApplyTime < 30f && _steamConfigApplied))
			{
				return;
			}
			_lastApplyTime = Time.time;
			try
			{
				ZLog.LogWarning((object)"[VBNetTweaks] Applying Steam buffer settings via reflection...");
				Type type = null;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					Type type2 = assembly.GetType("Steamworks.SteamNetworkingUtils");
					if (type2 != null)
					{
						type = type2;
						break;
					}
					type2 = assembly.GetType("Steamworks.SteamGameServerNetworkingUtils");
					if (type2 != null)
					{
						type = type2;
						break;
					}
				}
				if (type == null)
				{
					ZLog.LogWarning((object)"[VBNetTweaks] SteamNetworkingUtils type not found, buffer settings skipped.");
					return;
				}
				MethodInfo setConfigMethod = type.GetMethod("SetConfigValue", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[5]
				{
					typeof(int),
					typeof(int),
					typeof(IntPtr),
					typeof(int),
					typeof(IntPtr)
				}, null);
				if (setConfigMethod == null)
				{
					ZLog.LogWarning((object)"[VBNetTweaks] SetConfigValue method not found, buffer settings skipped.");
					return;
				}
				Type configValueType = null;
				Type type3 = null;
				Type type4 = null;
				Assembly[] assemblies2 = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly2 in assemblies2)
				{
					if (configValueType == null)
					{
						configValueType = assembly2.GetType("Steamworks.ESteamNetworkingConfigValue");
					}
					if (type3 == null)
					{
						type3 = assembly2.GetType("Steamworks.ESteamNetworkingConfigScope");
					}
					if (type4 == null)
					{
						type4 = assembly2.GetType("Steamworks.ESteamNetworkingConfigDataType");
					}
					if (configValueType != null && type3 != null && type4 != null)
					{
						break;
					}
				}
				if (configValueType == null || type3 == null || type4 == null)
				{
					ZLog.LogWarning((object)"[VBNetTweaks] Steam enums not found, buffer settings skipped.");
					return;
				}
				object globalScope = Enum.Parse(type3, "k_ESteamNetworkingConfig_Global");
				object intDataType = Enum.Parse(type4, "k_ESteamNetworkingConfig_Int32");
				int num = Math.Max(524288, VBNetTweaks.SteamSendBufferSizeKB.Value * 1024);
				SetConfigValue("k_ESteamNetworkingConfig_SendBufferSize", num);
				SetConfigValue("k_ESteamNetworkingConfig_RecvBufferSize", num);
				SetConfigValue("k_ESteamNetworkingConfig_RecvMaxMessageSize", 4194304);
				int num2 = Math.Max(262144, VBNetTweaks.SteamSendRateMaxKB.Value * 1024 / 2);
				SetConfigValue("k_ESteamNetworkingConfig_SendRateMin", num2);
				_steamConfigApplied = true;
				ZLog.LogWarning((object)$"[VBNetTweaks] Steam buffers applied: SendBuffer={num / 1024}KB, MinRate={num2 / 1024}KB/s");
				void SetConfigValue(string keyName, int value)
				{
					try
					{
						object obj = Enum.Parse(configValueType, keyName);
						GCHandle gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned);
						try
						{
							setConfigMethod.Invoke(null, new object[5]
							{
								(int)obj,
								(int)globalScope,
								IntPtr.Zero,
								(int)intDataType,
								gCHandle.AddrOfPinnedObject()
							});
						}
						finally
						{
							gCHandle.Free();
						}
					}
					catch (Exception ex2)
					{
						ZLog.LogWarning((object)("[VBNetTweaks] Failed to set " + keyName + ": " + ex2.Message));
					}
				}
			}
			catch (Exception ex)
			{
				ZLog.LogError((object)("[VBNetTweaks] Failed to apply Steam buffer settings: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Update")]
	public static class ZNet_Paths
	{
		[HarmonyPostfix]
		public static void Postfix(ZNet __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)ZNet.instance))
			{
				PerformanceMonitor.Track("ZNet.Update", delegate
				{
				});
			}
		}
	}
}
namespace VBNetTweaks.Utils
{
	public static class PerformanceMonitor
	{
		private struct Sample
		{
			public string Name;

			public float TotalTime;

			public int Count;

			public float LastLogTime;
		}

		private static Dictionary<string, Sample> _samples = new Dictionary<string, Sample>();

		private const float LOG_INTERVAL = 5f;

		public static void Track(string name, Action action)
		{
			if (!VBNetTweaks.DebugEnabled.Value)
			{
				action();
				return;
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			action();
			stopwatch.Stop();
			if (!_samples.TryGetValue(name, out var value))
			{
				Sample sample = default(Sample);
				sample.Name = name;
				value = sample;
			}
			value.TotalTime += stopwatch.ElapsedMilliseconds;
			value.Count++;
			float time = Time.time;
			if (time - value.LastLogTime > 5f)
			{
				float num = value.TotalTime / (float)value.Count;
				Helper.LogDebug($"{name}: avg={num:F2}ms over {value.Count} samples");
				value.TotalTime = 0f;
				value.Count = 0;
				value.LastLogTime = time;
			}
			_samples[name] = value;
		}
	}
	[HarmonyPatch]
	public static class PlayerCache
	{
		private static List<Player> _cachedPlayers = new List<Player>();

		private static Dictionary<long, Player> _playersById = new Dictionary<long, Player>();

		private static Dictionary<long, bool> _playerAttachedState = new Dictionary<long, bool>();

		private static Dictionary<long, ZDOID> _playerShipMap = new Dictionary<long, ZDOID>();

		private static int _cachedFrame = -1;

		private static float _cachedTime = -1f;

		public static List<Player> GetAll()
		{
			return GetCached();
		}

		public static List<Player> GetCurrentFrame()
		{
			return GetCached(0f);
		}

		public static List<Player> GetCached(float maxAgeSeconds = 0.5f)
		{
			if (Time.time - _cachedTime > maxAgeSeconds || _cachedFrame != Time.frameCount)
			{
				RefreshCache();
				_cachedTime = Time.time;
				_cachedFrame = Time.frameCount;
			}
			return _cachedPlayers;
		}

		public static Player GetById(long id)
		{
			if (_cachedFrame != Time.frameCount)
			{
				RefreshCache();
			}
			Player value;
			return _playersById.TryGetValue(id, out value) ? value : null;
		}

		public static bool IsPlayerOnShip(long playerId)
		{
			return _playerShipMap.ContainsKey(playerId);
		}

		public static bool IsPlayerAttached(long playerId)
		{
			bool value;
			return _playerAttachedState.TryGetValue(playerId, out value) && value;
		}

		public static ZDOID GetPlayerShip(long playerId)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			ZDOID value;
			return (ZDOID)(_playerShipMap.TryGetValue(playerId, out value) ? value : default(ZDOID));
		}

		public static void UpdatePlayerState(long playerId, bool attached, ZDOID shipId)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			_playerAttachedState[playerId] = attached;
			if (((ZDOID)(ref shipId)).IsNone())
			{
				_playerShipMap.Remove(playerId);
			}
			else
			{
				_playerShipMap[playerId] = shipId;
			}
		}

		public static void RemovePlayer(long playerId)
		{
			_playersById.Remove(playerId);
			_playerAttachedState.Remove(playerId);
			_playerShipMap.Remove(playerId);
		}

		private static void RefreshCache()
		{
			_cachedPlayers.Clear();
			_playersById.Clear();
			List<Player> allPlayers = Player.GetAllPlayers();
			_cachedPlayers.AddRange(allPlayers);
			foreach (Player item in allPlayers)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					long playerID = item.GetPlayerID();
					_playersById[playerID] = item;
				}
			}
			ZLog.Log((object)$"PlayerCache refreshed: {_cachedPlayers.Count} players");
		}

		public static void Invalidate()
		{
			_cachedFrame = -1;
			_cachedTime = -1f;
		}

		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		[HarmonyPostfix]
		private static void OnNewConnection(ZNet __instance, ZNetPeer peer)
		{
			Invalidate();
		}

		[HarmonyPatch(typeof(ZNet), "Disconnect")]
		[HarmonyPostfix]
		private static void OnDisconnect(ZNet __instance, ZNetPeer peer)
		{
			Invalidate();
			if (peer != null)
			{
				RemovePlayer(peer.m_uid);
			}
		}

		[HarmonyPatch(typeof(Player), "AttachStart")]
		[HarmonyPostfix]
		private static void OnAttachStart(Player __instance)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			long playerID = __instance.GetPlayerID();
			UpdatePlayerState(playerID, attached: true, default(ZDOID));
		}

		[HarmonyPatch(typeof(Player), "AttachStop")]
		[HarmonyPostfix]
		private static void OnAttachStop(Player __instance)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			long playerID = __instance.GetPlayerID();
			UpdatePlayerState(playerID, attached: false, default(ZDOID));
		}
	}
	public static class Helper
	{
		public static bool IsServer()
		{
			return Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer();
		}

		public static ZNet SafeZNetInstance()
		{
			return ZNet.instance;
		}

		public static void LogErrorWithContext(string module, string message, Exception ex = null)
		{
			string text = ((ex != null) ? (" [" + ex.Message + "]") : "");
			Debug.LogError((object)("[VBNetTweaks][" + module + "] " + message + text));
		}

		public static bool IsServerInitialized()
		{
			return IsServer() && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer();
		}

		public static void LogDebug(string message)
		{
			if (VBNetTweaks.DebugEnabled.Value)
			{
				Debug.LogWarning((object)("[VBNetTweaks] " + message));
			}
		}

		public static void LogVerbose(string message)
		{
			if (VBNetTweaks.VerboseLogging.Value)
			{
				Debug.LogWarning((object)("[VBNetTweaks] " + message));
			}
		}
	}
}