Decompiled source of VBNetTweaks v0.4.0

VBNetTweaks.dll

Decompiled a month 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 BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Steamworks;
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("VitByr")]
[assembly: AssemblyProduct("VBNetTweaks")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d9c87954-ce20-459d-81ec-96599caed427")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 MapPositionSync
	{
		private class MapTrackData
		{
			public struct Snapshot
			{
				public float time;

				public Vector3 pos;
			}

			private readonly List<Snapshot> _snapshots = new List<Snapshot>();

			private Vector3 _lastRealPos;

			private float _lastRealChangeTime;

			private Vector3 _velocity;

			private const int MAX_SNAPSHOTS = 30;

			public void AddSnapshot(float time, Vector3 pos)
			{
				//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: 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)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_0120: Unknown result type (might be due to invalid IL or missing references)
				//IL_0121: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: 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_00a8: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				if (_snapshots.Count > 0)
				{
					Snapshot snapshot = _snapshots[_snapshots.Count - 1];
					if (snapshot.pos == pos)
					{
						_snapshots[_snapshots.Count - 1] = new Snapshot
						{
							time = time,
							pos = pos
						};
						return;
					}
					float num = time - snapshot.time;
					if (num > 0.05f && num < 5f)
					{
						Vector3 val = pos - snapshot.pos;
						_velocity = Vector3.ClampMagnitude(val / num, 100f);
					}
					else
					{
						_velocity = Vector3.zero;
					}
				}
				_snapshots.Add(new Snapshot
				{
					time = time,
					pos = pos
				});
				while (_snapshots.Count > 30)
				{
					_snapshots.RemoveAt(0);
				}
				_lastRealPos = pos;
				_lastRealChangeTime = time;
			}

			public bool TryGetInterpolated(float renderTime, float maxPredictionTime, float maxPredictionSpeed, out Vector3 result)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_0106: Unknown result type (might be due to invalid IL or missing references)
				//IL_010b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: 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_017d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0184: Unknown result type (might be due to invalid IL or missing references)
				//IL_0189: Unknown result type (might be due to invalid IL or missing references)
				result = Vector3.zero;
				if (_snapshots.Count == 0)
				{
					return false;
				}
				if (renderTime <= _snapshots[0].time)
				{
					result = _snapshots[0].pos;
					return true;
				}
				if (renderTime >= _snapshots[_snapshots.Count - 1].time)
				{
					Snapshot snapshot = _snapshots[_snapshots.Count - 1];
					float num = renderTime - snapshot.time;
					if (num > maxPredictionTime)
					{
						num = maxPredictionTime;
					}
					Vector3 val = _velocity * num;
					if (((Vector3)(ref val)).magnitude > maxPredictionSpeed * num)
					{
						val = ((Vector3)(ref val)).normalized * maxPredictionSpeed * num;
					}
					result = snapshot.pos + val;
					return true;
				}
				for (int i = 1; i < _snapshots.Count; i++)
				{
					if (renderTime <= _snapshots[i].time)
					{
						Snapshot snapshot2 = _snapshots[i - 1];
						Snapshot snapshot3 = _snapshots[i];
						float num2 = Mathf.InverseLerp(snapshot2.time, snapshot3.time, renderTime);
						result = Vector3.Lerp(snapshot2.pos, snapshot3.pos, num2);
						return true;
					}
				}
				result = _snapshots[_snapshots.Count - 1].pos;
				return true;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static CoroutineHandler <0>__OnServerReceiveMapPos;

			public static CoroutineHandler <1>__OnClientReceiveMapPos;
		}

		private static CustomRPC _mapPositionRPC;

		private static float _mapPosTimer;

		private static readonly Dictionary<ZDOID, MapTrackData> _mapTracks = new Dictionary<ZDOID, MapTrackData>();

		public static void Initialize()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			if (_mapPositionRPC == null)
			{
				NetworkManager instance = NetworkManager.Instance;
				object obj = <>O.<0>__OnServerReceiveMapPos;
				if (obj == null)
				{
					CoroutineHandler val = OnServerReceiveMapPos;
					<>O.<0>__OnServerReceiveMapPos = val;
					obj = (object)val;
				}
				object obj2 = <>O.<1>__OnClientReceiveMapPos;
				if (obj2 == null)
				{
					CoroutineHandler val2 = OnClientReceiveMapPos;
					<>O.<1>__OnClientReceiveMapPos = val2;
					obj2 = (object)val2;
				}
				_mapPositionRPC = instance.AddRPC("VBNet_MapPositions", (CoroutineHandler)obj, (CoroutineHandler)obj2);
				Helper.LogDebug("[MapPositionSync] RPC initialized");
			}
		}

		[HarmonyPatch(typeof(ZNet), "Update")]
		[HarmonyPostfix]
		private static void ZNet_Update_MapPos(ZNet __instance)
		{
			if (VBNetTweaks.c_ModuleMapPositionSync.Value && __instance.IsServer() && _mapPositionRPC != null)
			{
				_mapPosTimer += Time.deltaTime;
				float value = VBNetTweaks.c_MapPositionSendInterval.Value;
				if (!(_mapPosTimer < value))
				{
					_mapPosTimer = 0f;
					SendMapPositions(__instance);
				}
			}
		}

		private static void SendMapPositions(ZNet net)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00ec: 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)
			List<ZNetPeer> peers = net.GetPeers();
			if (peers.Count == 0)
			{
				return;
			}
			List<(ZDOID, Vector3)> list = new List<(ZDOID, Vector3)>();
			foreach (ZNetPeer item in peers)
			{
				if (item.IsReady() && item.m_publicRefPos && !((ZDOID)(ref item.m_characterID)).IsNone())
				{
					list.Add((item.m_characterID, item.m_refPos));
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			ZPackage val = new ZPackage();
			val.Write(list.Count);
			foreach (var (val2, val3) in list)
			{
				val.Write(val2);
				val.Write(val3);
			}
			_mapPositionRPC.SendPackage(ZRoutedRpc.Everybody, val);
			if (VBNetTweaks.c_VerboseLogging.Value)
			{
				Helper.LogVerbose($"[MapPositionSync] Sent {list.Count} positions");
			}
		}

		private static IEnumerator OnServerReceiveMapPos(long sender, ZPackage pkg)
		{
			yield break;
		}

		private static IEnumerator OnClientReceiveMapPos(long sender, ZPackage pkg)
		{
			if (!VBNetTweaks.c_ModuleMapPositionSync.Value || Helper.IsServer() || (Object)(object)ZNet.instance == (Object)null)
			{
				yield break;
			}
			ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
			if (serverPeer == null || sender != serverPeer.m_uid)
			{
				yield break;
			}
			try
			{
				int count = pkg.ReadInt();
				float now = Time.time;
				for (int i = 0; i < count; i++)
				{
					ZDOID id = pkg.ReadZDOID();
					Vector3 pos = pkg.ReadVector3();
					if (!_mapTracks.TryGetValue(id, out var track))
					{
						track = new MapTrackData();
						_mapTracks[id] = track;
					}
					track.AddSnapshot(now, pos);
					track = null;
				}
				if (VBNetTweaks.c_VerboseLogging.Value && count > 0)
				{
					Helper.LogVerbose($"[MapPositionSync] Received {count} positions");
				}
			}
			catch (Exception ex)
			{
				Helper.LogDebug("[MapPositionSync] Error processing positions: " + ex.Message);
			}
		}

		[HarmonyPatch(typeof(Minimap), "UpdatePlayerPins")]
		[HarmonyPostfix]
		private static void Minimap_UpdatePlayerPins_Postfix(Minimap __instance, float dt)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			if (!VBNetTweaks.c_ModuleMapPositionSync.Value || Helper.IsServer() || __instance.m_playerPins == null || __instance.m_tempPlayerInfo == null)
			{
				return;
			}
			int num = Mathf.Min(__instance.m_playerPins.Count, __instance.m_tempPlayerInfo.Count);
			if (num == 0)
			{
				return;
			}
			float renderTime = Time.time - VBNetTweaks.c_MapInterpolationDelay.Value;
			float value = VBNetTweaks.c_MapMaxPredictionTime.Value;
			float value2 = VBNetTweaks.c_MapMaxPredictionSpeed.Value;
			float value3 = VBNetTweaks.c_MapTeleportThreshold.Value;
			for (int i = 0; i < num; i++)
			{
				PinData val = __instance.m_playerPins[i];
				PlayerInfo val2 = __instance.m_tempPlayerInfo[i];
				if (!val2.m_publicPosition)
				{
					continue;
				}
				ZDOID characterID = val2.m_characterID;
				if (((ZDOID)(ref characterID)).IsNone())
				{
					continue;
				}
				if (_mapTracks.TryGetValue(characterID, out var value4))
				{
					if (value4.TryGetInterpolated(renderTime, value, value2, out var result))
					{
						val.m_pos = result;
					}
					else
					{
						val.m_pos = val2.m_position;
					}
				}
				else
				{
					val.m_pos = val2.m_position;
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "OnDestroy")]
		[HarmonyPostfix]
		private static void ClearCache()
		{
			_mapTracks.Clear();
		}
	}
	[BepInPlugin("VitByr.VBNetTweaks", "VBNetTweaks", "0.4.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")]
	[BepInIncompatibility("sighsorry.SkadiNet")]
	[BepInIncompatibility("redseiko.valheim.returntosender")]
	[BepInIncompatibility("com.maxsch.valheim.TimeoutLimit")]
	[BepInIncompatibility("dzk.warheimnetwork")]
	public class VBNetTweaks : BaseUnityPlugin
	{
		private const string ModName = "VBNetTweaks";

		private const string ModVersion = "0.4.0";

		private const string ModGUID = "VitByr.VBNetTweaks";

		public CustomRPC _configSyncRPC;

		private ConfigFile _clientConfig;

		public static ManualLogSource Logger;

		public static ConfigEntry<Language> c_ConfigLanguage;

		public static ConfigEntry<bool> c_ModEnabled;

		public static ConfigEntry<bool> c_DebugEnabled;

		public static ConfigEntry<bool> c_VerboseLogging;

		public static ConfigEntry<bool> c_ModuleSteamOptimizations;

		public static ConfigEntry<bool> c_ModuleZDOOptimization;

		public static ConfigEntry<bool> c_ModuleShipSync;

		public static ConfigEntry<bool> c_ModuleZSyncTransformOptimization;

		public static ConfigEntry<bool> c_ModuleMapPositionSync;

		public static ConfigEntry<int> c_SteamSendRateMaxKB;

		public static ConfigEntry<int> c_SteamSendBufferSizeKB;

		public static ConfigEntry<float> c_SteamTimeoutConnected;

		public static ConfigEntry<float> c_SteamTimeoutKeepalive;

		public static ConfigEntry<int> c_SteamRecvMaxMessageSize;

		public static ConfigEntry<int> c_SteamSendRateMaxKB_S;

		public static ConfigEntry<int> c_SteamSendBufferSizeKB_S;

		public static ConfigEntry<int> c_ZDOQueueLimit;

		public static ConfigEntry<float> c_SendInterval_S;

		public static ConfigEntry<int> c_PeersPerUpdate_S;

		public static ConfigEntry<int> c_ZDOQueueLimit_S;

		public static ConfigEntry<float> c_FlushThresholdPercent_S;

		public static ConfigEntry<float> c_SmoothPosition;

		public static ConfigEntry<float> c_SmoothRotation;

		public static ConfigEntry<float> c_MicroThreshold;

		public static ConfigEntry<float> c_ClientDistanceThreshold;

		public static ConfigEntry<float> c_TeleportDistanceThreshold;

		public static ConfigEntry<float> c_TeleportRotationThreshold;

		public static ConfigEntry<float> c_MapPositionSendInterval;

		public static ConfigEntry<float> c_MapInterpolationDelay;

		public static ConfigEntry<float> c_MapMaxPredictionSpeed;

		public static ConfigEntry<float> c_MapMaxPredictionTime;

		public static ConfigEntry<float> c_MapTeleportThreshold;

		private Harmony _harmony;

		public static VBNetTweaks Instance { get; private set; }

		private void Awake()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			//IL_00cb: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			_clientConfig = new ConfigFile(Path.Combine(Paths.ConfigPath, "VitByr/VBNetTweaks/MainConfig.cfg"), true);
			SynchronizationManager.Instance.RegisterCustomConfig(_clientConfig);
			InitClientConfigs();
			InitServerConfigs();
			c_ModEnabled = ConfigFileExtensions.BindConfig<bool>(_clientConfig, "00 - Master", "ModEnabled", true, (c_ConfigLanguage.Value == Language.Russian) ? "Полностью включить/выключить мод VBNetTweaks" : "Completely enable/disable VBNetTweaks mod", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			if (c_ModEnabled.Value)
			{
				_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 (c_ModuleMapPositionSync.Value)
				{
					MapPositionSync.Initialize();
					_harmony.PatchAll(typeof(MapPositionSync));
				}
				_harmony.PatchAll(typeof(ZSteamSocket_Patchs));
				_harmony.PatchAll(typeof(ShipSyncFix));
				_harmony.PatchAll(typeof(NetworkSyncPatches));
				_harmony.PatchAll(typeof(ZDONetworkOptimizer));
				Helper.LogDebug("Режим отладки включен");
			}
		}

		private void InitClientConfigs()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			string text = "00 - Language";
			c_ConfigLanguage = ((BaseUnityPlugin)this).Config.Bind<Language>(text, "Language", Language.Russian, new ConfigDescription("Select interface language / Выберите язык интерфейса\nRequired Restart / Требуется рестарт", (AcceptableValueBase)null, Array.Empty<object>()));
			string text2 = "01 - Debug";
			c_DebugEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>(text2, "DebugEnabled", false, (c_ConfigLanguage.Value == Language.Russian) ? "Включить отладочный вывод" : "Enable debug output");
			c_VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>(text2, "VerboseLogging", false, (c_ConfigLanguage.Value == Language.Russian) ? "Включить подробное логирование" : "Enable verbose logging");
			string text3 = "02 - Modules";
			c_ModuleSteamOptimizations = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "SteamOptimizations", true, (c_ConfigLanguage.Value == Language.Russian) ? "Оптимизации Steam сокета" : "Steam socket optimizations", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_ModuleZDOOptimization = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "ZDOOptimization", true, (c_ConfigLanguage.Value == Language.Russian) ? "Оптимизация ZDO отправок" : "Optimization ZDO sender", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_ModuleShipSync = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "ShipSync", true, (c_ConfigLanguage.Value == Language.Russian) ? "Синхронизация на кораблях" : "On ship synchronization", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_ModuleZSyncTransformOptimization = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "ZSyncTransformOptimization", true, (c_ConfigLanguage.Value == Language.Russian) ? "Оптимизация движения игроков и мобов" : "Optimizing the movement of players and mobs", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_ModuleMapPositionSync = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "MapPositionSync", true, (c_ConfigLanguage.Value == Language.Russian) ? "Включить плавные маркеры игроков на карте\nУлучшает отображение позиций игроков" : "Enable smooth player markers on map\nImproves display of player positions", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text4 = "03 - Client Steam Settings";
			c_SteamSendRateMaxKB = ConfigFileExtensions.BindConfig<int>(_clientConfig, text4, "MaxRateKB", 2048, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальная скорость отправки Steam (vanilla = 150 KB/s)" : "Maximum Steam send rate (vanilla = 150 KB/s)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_SteamSendBufferSizeKB = ConfigFileExtensions.BindConfig<int>(_clientConfig, text4, "SendBufferSizeKB", 2048, (c_ConfigLanguage.Value == Language.Russian) ? "Размер буфера отправки Steam в KB (vanilla = ~260KB). Рекомендуется 1024-4096" : "Steam send buffer size in KB (vanilla = ~260KB). Recommended 1024-4096", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_SteamTimeoutConnected = ConfigFileExtensions.BindConfig<float>(_clientConfig, text4, "TimeoutConnected", 120000f, (c_ConfigLanguage.Value == Language.Russian) ? "Таймаут соединения Steam (миллисекунды)\nЕсли соединение неактивно дольше этого времени — оно будет разорвано\nvanilla: 30000 (30 секунд), рекомендуется: 60000-180000" : "Steam connection timeout (milliseconds)\nIf connection is idle longer than this — it will be closed\nvanilla: 30000 (30 sec), recommended: 60000-180000", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_SteamTimeoutKeepalive = ConfigFileExtensions.BindConfig<float>(_clientConfig, text4, "TimeoutKeepalive", 30000f, (c_ConfigLanguage.Value == Language.Russian) ? "Интервал Keep-Alive Steam (миллисекунды)\nКак часто отправлять пинг для поддержания соединения\nvanilla: 30000 (30 секунд), рекомендуется: 15000-60000" : "Steam Keep-Alive interval (milliseconds)\nHow often to send ping to keep connection alive\nvanilla: 30000 (30 sec), recommended: 15000-60000", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_SteamRecvMaxMessageSize = ConfigFileExtensions.BindConfig<int>(_clientConfig, text4, "RecvMaxMessageSize", 8, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальный размер принимаемого сообщения Steam (мегабайты)\nБольшие пакеты будут отклонены\nvanilla: ~1-2 MB, рекомендуется: 4-16 MB" : "Maximum Steam receive message size (megabytes)\nLarge packets will be rejected\nvanilla: ~1-2 MB, recommended: 4-16 MB", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text5 = "04 - Client ZDO Settings";
			c_ZDOQueueLimit = ConfigFileExtensions.BindConfig<int>(_clientConfig, text5, "ZDOQueueLimit", 10240, (c_ConfigLanguage.Value == Language.Russian) ? "Размер буфера отправки ZDO пакетов (vanilla = 10240 байт)" : "ZDO packet send buffer size (vanilla = 10240 bytes)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text6 = "05 - Transform Settings";
			c_SmoothPosition = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "SmoothPosition", 0.1f, (c_ConfigLanguage.Value == Language.Russian) ? "Сглаживание позиции (выше = плавнее, но больше задержка) (vanilla: 0.20)" : "Position smoothing value (vanilla: 0.20)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_SmoothRotation = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "SmoothRotation", 0.3f, (c_ConfigLanguage.Value == Language.Russian) ? "Значение сглаживания поворота (vanilla: 0.50)" : "Rotation smoothing value (vanilla: 0.50)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_MicroThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "MicroThreshold", 0.002f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог микро-движений (выше = меньше обновлений) (vanilla: 0.001)" : "Micro-movement threshold (vanilla: 0.001)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_ClientDistanceThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "ClientDistanceThreshold", 0.005f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог дистанции для клиентской синхронизации (vanilla: 0.01)" : "Client distance threshold (vanilla: 0.01)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_TeleportDistanceThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "TeleportDistanceThreshold", 3f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог дистанции для мгновенного телепорта (метры)\nЕсли объект сместился больше этого значения — телепорт без сглаживания\nvanilla: 5, рекомендуется: 5-20" : "Distance threshold for instant teleport (meters)\nIf object moves beyond this value — teleport without smoothing\nvanilla: 5, recommended: 5-20", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_TeleportRotationThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "TeleportRotationThreshold", 35f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог угла для мгновенного телепорта поворота (градусы)\nЕсли объект повернулся больше этого значения — телепорт без сглаживания\nvanilla: 45, рекомендуется: 30-90" : "Angle threshold for instant rotation teleport (degrees)\nIf object rotates beyond this value — teleport without smoothing\nvanilla: 45, recommended: 30-90", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text7 = "08 - Map Positions";
			c_MapPositionSendInterval = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "SendInterval", 0.5f, (c_ConfigLanguage.Value == Language.Russian) ? "Интервал отправки позиций игроков (сек)\nМеньше = плавнее, но больше трафик\nvanilla: 2.0, рекомендуется: 0.2-0.5" : "Player position send interval (sec)\nLower = smoother, but more traffic\nvanilla: 2.0, recommended: 0.2-0.5", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_MapInterpolationDelay = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "InterpolationDelay", 0.1f, (c_ConfigLanguage.Value == Language.Russian) ? "Задержка интерполяции маркеров (сек)\nМаркеры будут отставать на это значение для плавности" : "Marker interpolation delay (sec)\nMarkers will lag by this value for smoothness", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_MapMaxPredictionSpeed = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "MaxPredictionSpeed", 40f, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальная скорость предсказания движения (м/с)\nОграничивает рывки при экстраполяции" : "Maximum movement prediction speed (m/s)\nLimits jerks during extrapolation", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_MapMaxPredictionTime = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "MaxPredictionTime", 0.05f, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальное время предсказания движения (сек)\nКак долго маркер двигается по инерции" : "Maximum movement prediction time (sec)\nHow long marker moves by inertia", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_MapTeleportThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "TeleportThreshold", 50f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог телепорта для маркеров (метры)\nЕсли игрок сместился дальше — маркер прыгнет мгновенно" : "Teleport threshold for markers (meters)\nIf player moves beyond — marker jumps instantly", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		}

		private void InitServerConfigs()
		{
			string text = "06 - Server Steam Settings";
			c_SteamSendRateMaxKB_S = ConfigFileExtensions.BindConfig<int>(_clientConfig, text, "MaxRateKB", 4096, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальная скорость отправки Steam (vanilla = 150 KB/s)" : "Maximum Steam send rate (vanilla = 150 KB/s)", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_SteamSendBufferSizeKB_S = ConfigFileExtensions.BindConfig<int>(_clientConfig, text, "SendBufferSizeKB", 4096, (c_ConfigLanguage.Value == Language.Russian) ? "Размер буфера отправки Steam в KB (vanilla = ~260KB). Рекомендуется 1024-4096" : "Steam send buffer size in KB (vanilla = ~260KB). Recommended 1024-4096", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text2 = "07 - Server ZDO Settings";
			c_SendInterval_S = ConfigFileExtensions.BindConfig<float>(_clientConfig, text2, "SendInterval", 0.02f, (c_ConfigLanguage.Value == Language.Russian) ? "Интервал отправки данных (vanilla = 0.05)" : "Data send interval (vanilla = 0.05)", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_PeersPerUpdate_S = ConfigFileExtensions.BindConfig<int>(_clientConfig, text2, "PeersPerUpdate", 10, (c_ConfigLanguage.Value == Language.Russian) ? "Количество пиров за один апдейт (vanilla = 1). Лучше ставить значение равное максимальному количеству слотов сервера." : "Peers per update (vanilla = 1). Better set equal to max server slots.", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_ZDOQueueLimit_S = ConfigFileExtensions.BindConfig<int>(_clientConfig, text2, "ZDOQueueLimit", 20480, (c_ConfigLanguage.Value == Language.Russian) ? "Размер буфера отправки ZDO пакетов (vanilla = 10240 байт)" : "ZDO packet send buffer size (vanilla = 10240 bytes)", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			c_FlushThresholdPercent_S = ConfigFileExtensions.BindConfig<float>(_clientConfig, text2, "FlushThresholdPercent", 0.2f, (c_ConfigLanguage.Value == Language.Russian) ? "Процент от ZDOQueueLimit для активации flush (0.0-1.0)\n0.1 = редкий flush (экономия трафика, но задержки)\n0.3 = оптимальный баланс (рекомендуется)\n0.5 = частый flush (меньше задержек, больше трафика)" : "Percentage of ZDOQueueLimit for flush activation (0.0-1.0)\n0.1 = rare flush (traffic saving, but delays)\n0.3 = optimal balance (recommended)\n0.5 = frequent flush (less delays, more traffic)", false, (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_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			try
			{
				val.Write(c_ModEnabled.Value);
				val.Write(c_ModuleSteamOptimizations.Value);
				val.Write(c_ModuleZDOOptimization.Value);
				val.Write(c_ModuleShipSync.Value);
				val.Write(c_ModuleZSyncTransformOptimization.Value);
				val.Write(c_SteamSendRateMaxKB.Value);
				val.Write(c_SteamSendBufferSizeKB.Value);
				val.Write(c_SteamTimeoutConnected.Value);
				val.Write(c_SteamTimeoutKeepalive.Value);
				val.Write(c_SteamRecvMaxMessageSize.Value);
				val.Write(c_ZDOQueueLimit.Value);
				val.Write(c_SmoothPosition.Value);
				val.Write(c_SmoothRotation.Value);
				val.Write(c_MicroThreshold.Value);
				val.Write(c_ClientDistanceThreshold.Value);
				val.Write(c_TeleportDistanceThreshold.Value);
				val.Write(c_TeleportRotationThreshold.Value);
				val.Write(c_MapPositionSendInterval.Value);
				val.Write(c_MapInterpolationDelay.Value);
				val.Write(c_MapMaxPredictionSpeed.Value);
				val.Write(c_MapMaxPredictionTime.Value);
				val.Write(c_MapTeleportThreshold.Value);
			}
			catch (Exception ex)
			{
				Helper.LogDebug("Error building config package: " + ex.Message);
				return new ZPackage();
			}
			return val;
		}

		private void ApplyConfigFromPackage(ZPackage pkg)
		{
			if (pkg == null || pkg.GetArray().Length == 0)
			{
				Helper.LogDebug("Received empty config package");
				return;
			}
			try
			{
				pkg.SetPos(0);
				c_ModEnabled.Value = pkg.ReadBool();
				c_ModuleSteamOptimizations.Value = pkg.ReadBool();
				c_ModuleZDOOptimization.Value = pkg.ReadBool();
				c_ModuleShipSync.Value = pkg.ReadBool();
				c_ModuleZSyncTransformOptimization.Value = pkg.ReadBool();
				c_SteamSendRateMaxKB.Value = pkg.ReadInt();
				c_SteamSendBufferSizeKB.Value = pkg.ReadInt();
				c_SteamTimeoutConnected.Value = pkg.ReadSingle();
				c_SteamTimeoutKeepalive.Value = pkg.ReadSingle();
				c_SteamRecvMaxMessageSize.Value = pkg.ReadInt();
				c_ZDOQueueLimit.Value = pkg.ReadInt();
				c_SmoothPosition.Value = pkg.ReadSingle();
				c_SmoothRotation.Value = pkg.ReadSingle();
				c_MicroThreshold.Value = pkg.ReadSingle();
				c_ClientDistanceThreshold.Value = pkg.ReadSingle();
				c_TeleportDistanceThreshold.Value = pkg.ReadSingle();
				c_TeleportRotationThreshold.Value = pkg.ReadSingle();
				c_MapPositionSendInterval.Value = pkg.ReadSingle();
				c_MapInterpolationDelay.Value = pkg.ReadSingle();
				c_MapMaxPredictionSpeed.Value = pkg.ReadSingle();
				c_MapMaxPredictionTime.Value = pkg.ReadSingle();
				c_MapTeleportThreshold.Value = pkg.ReadSingle();
			}
			catch (Exception ex)
			{
				Helper.LogDebug("Error applying config package: " + ex.Message);
			}
		}

		private IEnumerator OnAdminConfigSync(long sender, ZPackage pkg)
		{
			if (!Helper.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);
			}
			Helper.LogDebug("Server config broadcast to all clients");
		}

		public IEnumerator OnClientConfigSync(long sender, ZPackage pkg)
		{
			Helper.LogDebug($"Клиент получил конфиг от сервера {sender}");
			ApplyConfigFromPackage(pkg);
			ConfigFileExtensions.SetSaveOnConfigSet(_clientConfig, true);
			_clientConfig.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(_clientConfig, 1000L);
			val.OnConfigFileReloaded += delegate
			{
				if (Helper.IsServer())
				{
					Helper.LogDebug("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)
			{
				yield break;
			}
			byte[] data = pkg.GetArray();
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				ZPackage copyPkg = new ZPackage(data);
				_configSyncRPC.SendPackage(new List<ZNetPeer> { peer }, copyPkg);
			}
			Helper.LogDebug("Server config broadcast to all clients");
		}

		private void OnDestroy()
		{
			ConfigFile clientConfig = _clientConfig;
			if (clientConfig != null)
			{
				clientConfig.Save();
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace VBNetTweaks.ZDOUtills
{
	[HarmonyPatch]
	public static class ZDONetworkOptimizer
	{
		private enum SyncPriority : byte
		{
			Default,
			Piece,
			Creature,
			Ship,
			Player
		}

		private static Vector3 _currentRefPos;

		private static readonly Dictionary<int, SyncPriority> _priorityCache = new Dictionary<int, SyncPriority>();

		public static int GetSafeQueueLimit()
		{
			return Mathf.Clamp(VBNetTweaks.c_ZDOQueueLimit.Value, 8192, 1048576);
		}

		[HarmonyPatch(typeof(ZDOMan), "SendZDOToPeers2")]
		[HarmonyPrefix]
		private static bool SendZDOToPeers2_Prefix(ZDOMan __instance, float dt)
		{
			if (!VBNetTweaks.c_ModuleZDOOptimization.Value)
			{
				return true;
			}
			OptimizedSendZDOToPeers(__instance, dt);
			return false;
		}

		public static void OptimizedSendZDOToPeers(ZDOMan man, float dt)
		{
			try
			{
				int count = man.m_peers.Count;
				if (count == 0)
				{
					return;
				}
				man.m_sendTimer += dt;
				float num = Mathf.Clamp(VBNetTweaks.c_SendInterval_S.Value, 0.01f, 0.2f);
				if (man.m_sendTimer < num)
				{
					return;
				}
				man.m_sendTimer = 0f;
				int num2 = Mathf.Clamp(VBNetTweaks.c_PeersPerUpdate_S.Value, 1, count);
				int num3 = ((man.m_nextSendPeer >= 0) ? man.m_nextSendPeer : 0);
				int num4 = 0;
				for (int i = 0; i < num2; i++)
				{
					int index = (num3 + i) % count;
					num4++;
					ZDOPeer val = man.m_peers[index];
					if (val == null)
					{
						continue;
					}
					ZNetPeer peer = val.m_peer;
					bool? obj;
					if (peer == null)
					{
						obj = null;
					}
					else
					{
						ISocket socket = peer.m_socket;
						obj = ((socket != null) ? new bool?(socket.IsConnected()) : ((bool?)null));
					}
					if (obj == true)
					{
						int sendQueueSize = val.m_peer.m_socket.GetSendQueueSize();
						int safeQueueLimit = GetSafeQueueLimit();
						if (sendQueueSize <= safeQueueLimit)
						{
							float num5 = Mathf.Clamp01(VBNetTweaks.c_FlushThresholdPercent_S.Value) * (float)safeQueueLimit;
							bool flag = (float)sendQueueSize <= num5;
							man.SendZDOs(val, flag);
						}
					}
				}
				man.m_nextSendPeer = (num3 + num4) % count;
			}
			catch (Exception arg)
			{
				Helper.LogDebug($" Error in OptimizedSendZDOToPeers: {arg}");
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "ServerSortSendZDOS")]
		[HarmonyPrefix]
		private static void ServerSortSendZDOS_Prefix(Vector3 refPos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_currentRefPos = refPos;
		}

		[HarmonyPatch(typeof(ZDOMan), "ServerSendCompare")]
		[HarmonyPrefix]
		private static bool CustomServerSendCompare(ZDO x, ZDO y, ref int __result)
		{
			if (!VBNetTweaks.c_ModuleZDOOptimization.Value)
			{
				return true;
			}
			if (!ZNet.instance.IsServer())
			{
				return true;
			}
			__result = CustomCompare(x, y);
			return false;
		}

		private static int CustomCompare(ZDO x, ZDO y)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			//IL_009d: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected I4, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected I4, but got Unknown
			if (x == null || y == null)
			{
				return 0;
			}
			bool flag = (int)x.Type == 1 && x.HasOwner() && x.GetOwner() != ZDOMan.s_compareReceiver;
			bool flag2 = (int)y.Type == 1 && y.HasOwner() && y.GetOwner() != ZDOMan.s_compareReceiver;
			if (flag && flag2)
			{
				return CompareFloats(x.m_tempSortValue, y.m_tempSortValue);
			}
			if (flag != flag2)
			{
				return (!flag) ? 1 : (-1);
			}
			if (x.Type != y.Type)
			{
				return ((int)y.Type).CompareTo((int)x.Type);
			}
			SyncPriority priority = GetPriority(x);
			SyncPriority priority2 = GetPriority(y);
			if (priority != priority2)
			{
				byte b = (byte)priority2;
				return b.CompareTo((byte)priority);
			}
			return CompareFloats(x.m_tempSortValue, y.m_tempSortValue);
		}

		private static int CompareFloats(float a, float b)
		{
			if (a < b)
			{
				return -1;
			}
			if (a > b)
			{
				return 1;
			}
			return 0;
		}

		private static SyncPriority GetPriority(ZDO zdo)
		{
			int prefab = zdo.GetPrefab();
			if (_priorityCache.TryGetValue(prefab, out var value))
			{
				return value;
			}
			SyncPriority syncPriority = SyncPriority.Default;
			if (Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
				if (Object.op_Implicit((Object)(object)prefab2))
				{
					if (Object.op_Implicit((Object)(object)prefab2.GetComponent<Player>()))
					{
						syncPriority = SyncPriority.Player;
					}
					else if (Object.op_Implicit((Object)(object)prefab2.GetComponent<Ship>()))
					{
						syncPriority = SyncPriority.Ship;
					}
					else if (Object.op_Implicit((Object)(object)prefab2.GetComponent<Character>()))
					{
						syncPriority = SyncPriority.Creature;
					}
					else if (Object.op_Implicit((Object)(object)prefab2.GetComponent<Piece>()))
					{
						syncPriority = SyncPriority.Piece;
					}
				}
			}
			_priorityCache[prefab] = syncPriority;
			return syncPriority;
		}
	}
}
namespace VBNetTweaks.Utils
{
	public enum Language
	{
		Russian,
		English
	}
	public static class SyncTuning
	{
		private static int _frame;

		private static float _smoothPos;

		private static float _smoothRot;

		private static float _microThreshold;

		private static float _clientDistance;

		private static float _teleportDistance;

		private static float _teleportRotation;

		private static void RefreshIfNeeded()
		{
			int frameCount = Time.frameCount;
			if (frameCount != _frame)
			{
				_frame = frameCount;
				_smoothPos = Mathf.Clamp(VBNetTweaks.c_SmoothPosition.Value, 0.01f, 1f);
				_smoothRot = Mathf.Clamp(VBNetTweaks.c_SmoothRotation.Value, 0.01f, 1f);
				_microThreshold = Mathf.Clamp(VBNetTweaks.c_MicroThreshold.Value, 0f, 0.05f);
				_clientDistance = Mathf.Clamp(VBNetTweaks.c_ClientDistanceThreshold.Value, 0f, 0.1f);
				_teleportDistance = Mathf.Clamp(VBNetTweaks.c_TeleportDistanceThreshold.Value, 1f, 100f);
				_teleportRotation = Mathf.Clamp(VBNetTweaks.c_TeleportRotationThreshold.Value, 10f, 180f);
			}
		}

		public static float GetSmoothPosition()
		{
			RefreshIfNeeded();
			return _smoothPos;
		}

		public static float GetSmoothRotation()
		{
			RefreshIfNeeded();
			return _smoothRot;
		}

		public static float GetMicroThreshold()
		{
			RefreshIfNeeded();
			return _microThreshold;
		}

		public static float GetClientDistanceThreshold()
		{
			RefreshIfNeeded();
			return _clientDistance;
		}

		public static float GetTeleportDistanceThreshold()
		{
			RefreshIfNeeded();
			return _teleportDistance;
		}

		public static float GetTeleportRotationThreshold()
		{
			RefreshIfNeeded();
			return _teleportRotation;
		}
	}
	public static class Helper
	{
		private static readonly Dictionary<int, bool> _creatureCache = new Dictionary<int, bool>();

		private static readonly Dictionary<int, bool> _shipCache = new Dictionary<int, bool>();

		public static bool IsCreature(ZDO zdo)
		{
			int prefab = zdo.GetPrefab();
			if (_creatureCache.TryGetValue(prefab, out var value))
			{
				return value;
			}
			bool flag = false;
			if (Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
				if (Object.op_Implicit((Object)(object)prefab2))
				{
					flag = Object.op_Implicit((Object)(object)prefab2.GetComponent<Humanoid>());
				}
			}
			_creatureCache[prefab] = flag;
			return flag;
		}

		public static bool IsShip(ZDO zdo)
		{
			int prefab = zdo.GetPrefab();
			if (_shipCache.TryGetValue(prefab, out var value))
			{
				return value;
			}
			bool flag = false;
			if (Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
				if (Object.op_Implicit((Object)(object)prefab2))
				{
					flag = Object.op_Implicit((Object)(object)prefab2.GetComponent<Ship>());
				}
			}
			_shipCache[prefab] = flag;
			return flag;
		}

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

		public static void LogDebug(string message)
		{
			if (VBNetTweaks.c_DebugEnabled.Value)
			{
				VBNetTweaks.Logger.LogWarning((object)message);
			}
		}

		public static void LogVerbose(string message)
		{
			if (VBNetTweaks.c_VerboseLogging.Value)
			{
				VBNetTweaks.Logger.LogInfo((object)message);
			}
		}
	}
}
namespace VBNetTweaks.Patches
{
	[HarmonyPatch]
	public static class NetworkSyncPatches
	{
		private static float _teleportBoostEnd;

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

		public static int GetQueueLimit()
		{
			return Mathf.Max(4096, Helper.IsServer() ? VBNetTweaks.c_ZDOQueueLimit_S.Value : VBNetTweaks.c_ZDOQueueLimit.Value);
		}

		[HarmonyPatch(typeof(ZSyncTransform), "SyncPosition")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> SyncPosition_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo operand = AccessTools.Method(typeof(SyncTuning), "GetSmoothPosition", (Type[])null, (Type[])null);
			MethodInfo operand2 = AccessTools.Method(typeof(SyncTuning), "GetSmoothRotation", (Type[])null, (Type[])null);
			MethodInfo operand3 = AccessTools.Method(typeof(SyncTuning), "GetMicroThreshold", (Type[])null, (Type[])null);
			MethodInfo operand4 = AccessTools.Method(typeof(SyncTuning), "GetTeleportDistanceThreshold", (Type[])null, (Type[])null);
			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].opcode = OpCodes.Call;
						list[i].operand = operand;
					}
					else if (Mathf.Approximately(num, 0.5f))
					{
						list[i].opcode = OpCodes.Call;
						list[i].operand = operand2;
					}
					else if (Mathf.Approximately(num, 0.001f))
					{
						list[i].opcode = OpCodes.Call;
						list[i].operand = operand3;
					}
					else if (Mathf.Approximately(num, 5f))
					{
						list[i].opcode = OpCodes.Call;
						list[i].operand = operand4;
					}
				}
			}
			return list;
		}

		[HarmonyPatch(typeof(ZSyncTransform), "ClientSync")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> ClientSync_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo operand = AccessTools.Method(typeof(SyncTuning), "GetSmoothPosition", (Type[])null, (Type[])null);
			MethodInfo operand2 = AccessTools.Method(typeof(SyncTuning), "GetSmoothRotation", (Type[])null, (Type[])null);
			MethodInfo operand3 = AccessTools.Method(typeof(SyncTuning), "GetMicroThreshold", (Type[])null, (Type[])null);
			MethodInfo operand4 = AccessTools.Method(typeof(SyncTuning), "GetClientDistanceThreshold", (Type[])null, (Type[])null);
			MethodInfo operand5 = AccessTools.Method(typeof(SyncTuning), "GetTeleportRotationThreshold", (Type[])null, (Type[])null);
			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].opcode = OpCodes.Call;
						list[i].operand = operand;
					}
					else if (Mathf.Approximately(num, 0.5f))
					{
						list[i].opcode = OpCodes.Call;
						list[i].operand = operand2;
					}
					else if (Mathf.Approximately(num, 0.001f))
					{
						list[i].opcode = OpCodes.Call;
						list[i].operand = operand3;
					}
					else if (Mathf.Approximately(num, 0.01f))
					{
						list[i].opcode = OpCodes.Call;
						list[i].operand = operand4;
					}
					else if (Mathf.Approximately(num, 45f))
					{
						list[i].opcode = OpCodes.Call;
						list[i].operand = operand5;
					}
				}
			}
			return list;
		}

		[HarmonyPatch(typeof(ZSyncTransform), "OwnerSync")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> OwnerSync_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo operand = AccessTools.Method(typeof(SyncTuning), "GetMicroThreshold", (Type[])null, (Type[])null);
			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].opcode = OpCodes.Call;
					list[i].operand = operand;
				}
			}
			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;
			MethodInfo operand = AccessTools.Method(typeof(NetworkSyncPatches), "GetQueueLimit", (Type[])null, (Type[])null);
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_I4 && (int)list[i].operand == 10240)
				{
					list[i].opcode = OpCodes.Call;
					list[i].operand = operand;
					num++;
				}
			}
			if (num < 2)
			{
				Helper.LogDebug("ZDOQueueLimit patch failed: found less than 2 instances of 10240!");
			}
			else if (num == 2)
			{
				if (Helper.IsServer())
				{
					Helper.LogDebug($"ZDOQueueLimit patch to: {VBNetTweaks.c_ZDOQueueLimit_S.Value}");
				}
				else
				{
					Helper.LogDebug($"ZDOQueueLimit patch to: {VBNetTweaks.c_ZDOQueueLimit.Value}");
				}
			}
			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();
			}
		}
	}
	public static class ShipSyncFix
	{
		private static float _lastDamageLog;

		[HarmonyPatch(typeof(ShipControlls), "RPC_RequestRespons")]
		[HarmonyPrefix]
		public static void OnControlGranted(ShipControlls __instance, long sender, bool granted)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!granted || !__instance.m_nview.IsValid() || sender != ZNet.GetUID())
			{
				return;
			}
			Ship ship = __instance.m_ship;
			if (!Object.op_Implicit((Object)(object)ship))
			{
				return;
			}
			ZNetView nview = ship.m_nview;
			if (Object.op_Implicit((Object)(object)nview) && nview.IsValid())
			{
				ZDO zDO = nview.GetZDO();
				if (zDO != null && zDO.GetOwner() != sender)
				{
					zDO.SetOwner(sender);
					ZDOMan.instance.ForceSendZDO(zDO.m_uid);
					Helper.LogVerbose($"[ShipOwnership] Player {sender} took ownership of ship");
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Ship), "UpdateWaterForce")]
		private static bool UpdateWaterForce_Prefix(Ship __instance, ref float depth, ref float time)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			float num = depth - __instance.m_lastDepth;
			float num2 = time - __instance.m_lastUpdateWaterForceTime;
			__instance.m_lastDepth = depth;
			__instance.m_lastUpdateWaterForceTime = time;
			if (num2 <= 0.001f)
			{
				return true;
			}
			float num3 = num / num2;
			if (num3 <= 0f && Mathf.Abs(num3) > __instance.m_minWaterImpactForce && time - __instance.m_lastWaterImpactTime > __instance.m_minWaterImpactInterval)
			{
				__instance.m_lastWaterImpactTime = time;
				__instance.m_waterImpactEffect.Create(((Component)__instance).transform.position, ((Component)__instance).transform.rotation, (Transform)null, 1f, -1);
				if (__instance.m_nview.IsOwner() && __instance.m_players.Count > 0)
				{
					HitData val = new HitData();
					val.m_damage.m_blunt = __instance.m_waterImpactDamage;
					val.m_point = ((Component)__instance).transform.position;
					val.m_dir = Vector3.up;
					__instance.m_destructible.Damage(val);
					if (VBNetTweaks.c_VerboseLogging.Value && Time.time - _lastDamageLog > 5f)
					{
						_lastDamageLog = Time.time;
						float num4 = Mathf.Abs(num3);
						Helper.LogVerbose($"[Ship] Water impact damage: speed={num4:F2}, threshold={__instance.m_minWaterImpactForce:F2}, players={__instance.m_players.Count}");
					}
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(Ship), "ApplyControlls")]
		[HarmonyPrefix]
		private static bool ApplyControlls_Prefix(Ship __instance, Vector3 dir)
		{
			//IL_001c: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!VBNetTweaks.c_ModuleShipSync.Value)
			{
				return true;
			}
			bool flag = (double)dir.z > 0.5;
			bool flag2 = (double)dir.z < -0.5;
			if (flag && !__instance.m_forwardPressed)
			{
				__instance.Forward();
			}
			if (flag2 && !__instance.m_backwardPressed)
			{
				__instance.Backward();
			}
			__instance.m_forwardPressed = flag;
			__instance.m_backwardPressed = flag2;
			float fixedDeltaTime = Time.fixedDeltaTime;
			float num = Mathf.Lerp(0.5f, 1f, Mathf.Abs(__instance.m_rudderValue));
			__instance.m_rudder = dir.x * num;
			__instance.m_rudderValue += __instance.m_rudder * __instance.m_rudderSpeed * fixedDeltaTime;
			__instance.m_rudderValue = Mathf.Clamp(__instance.m_rudderValue, -1f, 1f);
			if (Time.time - __instance.m_sendRudderTime > 0.05f)
			{
				__instance.m_sendRudderTime = Time.time;
				__instance.m_nview.InvokeRPC("Rudder", new object[1] { __instance.m_rudderValue });
			}
			return false;
		}
	}
	[HarmonyPatch]
	public static class ZSteamSocket_Patchs
	{
		private static readonly float TIMEOUT_CONNECTED = VBNetTweaks.c_SteamTimeoutConnected.Value;

		private static readonly float TIMEOUT_KEEPALIVE = VBNetTweaks.c_SteamTimeoutKeepalive.Value;

		private static readonly int RECV_MAX_MESSAGE_SIZE = VBNetTweaks.c_SteamRecvMaxMessageSize.Value * 1024 * 1024;

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")]
		private static IEnumerable<CodeInstruction> RegisterGlobalCallbacks_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			if (!VBNetTweaks.c_ModuleSteamOptimizations.Value)
			{
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			bool flag = false;
			bool flag2 = false;
			int num = Math.Max(64, Helper.IsServer() ? VBNetTweaks.c_SteamSendRateMaxKB_S.Value : VBNetTweaks.c_SteamSendRateMaxKB.Value) * 1024;
			for (int i = 0; i < list.Count; i++)
			{
				CodeInstruction val = list[i];
				if (val.opcode == OpCodes.Ldc_R4 && val.operand is float num2 && Math.Abs(num2 - 30000f) < 0.001f)
				{
					list[i].operand = TIMEOUT_CONNECTED;
					flag = true;
					Helper.LogDebug($"TimeoutConnected: 30000 -> {TIMEOUT_CONNECTED}");
				}
				if (val.opcode == OpCodes.Ldc_I4 && val.operand is int num3 && num3 == 153600)
				{
					list[i].operand = num;
					flag2 = true;
					Helper.LogDebug($"SendRate: 153600 -> {num}");
				}
			}
			if (!flag)
			{
				Helper.LogDebug("TimeoutConnected constant 30000 not found!");
			}
			if (!flag2)
			{
				Helper.LogDebug("SendRate constant 153600 not found!");
			}
			return list;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")]
		private static void ApplySteamBuffers()
		{
			if (!VBNetTweaks.c_ModuleSteamOptimizations.Value)
			{
				return;
			}
			try
			{
				int num = Math.Max(524288, (Helper.IsServer() ? VBNetTweaks.c_SteamSendBufferSizeKB_S.Value : VBNetTweaks.c_SteamSendBufferSizeKB.Value) * 1024);
				int num2 = Math.Max(64, Helper.IsServer() ? VBNetTweaks.c_SteamSendRateMaxKB_S.Value : VBNetTweaks.c_SteamSendRateMaxKB.Value) * 1024;
				int value = Math.Max(262144, num2 / 4);
				SetConfigInt((ESteamNetworkingConfigValue)9, num);
				Helper.LogDebug($"SendBufferSize: {num / 1024}KB");
				SetConfigInt((ESteamNetworkingConfigValue)10, num);
				Helper.LogDebug($"RecvBufferSize: {num / 1024}KB");
				SetConfigInt((ESteamNetworkingConfigValue)12, RECV_MAX_MESSAGE_SIZE);
				Helper.LogDebug($"RecvMaxMessageSize: {RECV_MAX_MESSAGE_SIZE / 1024 / 1024}MB");
				SetConfigFloat((ESteamNetworkingConfigValue)1, TIMEOUT_KEEPALIVE);
				Helper.LogDebug($"TimeoutKeepAlive: {TIMEOUT_KEEPALIVE}s");
				SetConfigInt((ESteamNetworkingConfigValue)10, value);
				SetConfigInt((ESteamNetworkingConfigValue)11, num2);
			}
			catch (Exception ex)
			{
				Helper.LogDebug("Failed to apply Steam buffers: " + ex.Message);
			}
		}

		private static void SetConfigInt(ESteamNetworkingConfigValue config, int value)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GCHandle gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned);
				try
				{
					SteamNetworkingUtils.SetConfigValue(config, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle.AddrOfPinnedObject());
				}
				finally
				{
					gCHandle.Free();
				}
			}
			catch (Exception ex)
			{
				Helper.LogDebug($"Failed to set int {config}: {ex.Message}");
			}
		}

		private static void SetConfigFloat(ESteamNetworkingConfigValue config, float value)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GCHandle gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned);
				try
				{
					SteamNetworkingUtils.SetConfigValue(config, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)3, gCHandle.AddrOfPinnedObject());
				}
				finally
				{
					gCHandle.Free();
				}
			}
			catch (Exception ex)
			{
				Helper.LogDebug($"Failed to set float {config}: {ex.Message}");
			}
		}
	}
}