Decompiled source of VBNetTweaks v0.2.7

VBNetTweaks.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
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 System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Steamworks;
using UnityEngine;
using VBNetTweaks.CompressionUtills;
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;
		}

		private class PlayerShipState
		{
			public Ship ship;

			public Vector3 localPos;

			public Quaternion localRot;

			public float lastUpdate;
		}

		private static readonly object _shipDataLock;

		private static readonly object _playerStatesLock;

		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 string RPC_SYNC_SHIP = "VBNT.SyncShip";

		public static bool ShipHasPlayers(ZDOID shipId)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			lock (_shipDataLock)
			{
				return _playersOnShip.ContainsKey(shipId);
			}
		}

		public static int GetPlayersOnShipCount(ZDOID shipId)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			lock (_shipDataLock)
			{
				int value;
				return _playersOnShip.TryGetValue(shipId, out value) ? value : 0;
			}
		}

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

		public static bool IsPlayerAttached(long playerId)
		{
			return PlayerCache.IsPlayerAttached(playerId);
		}

		static ShipSyncSystem()
		{
			_shipDataLock = new object();
			_playerStatesLock = new object();
			_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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			lock (_shipDataLock)
			{
				_shipData.Remove(uid);
			}
			lock (_playerStatesLock)
			{
				if (_playerShipMap.TryGetValue(uid, out var value))
				{
					lock (_shipDataLock)
					{
						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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_00c7: 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_012d: 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_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			if (Helper.IsServer() || !Object.op_Implicit((Object)(object)__instance))
			{
				return;
			}
			Ship component = ((Component)__instance).GetComponent<Ship>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			ZDO zDO = __instance.GetZDO();
			if (zDO == null || !zDO.IsValid())
			{
				return;
			}
			long owner = zDO.GetOwner();
			if (owner == 0 || owner == ZNet.GetUID())
			{
				return;
			}
			Vector3 position = zDO.GetPosition();
			Quaternion rotation = zDO.GetRotation();
			if (!_shipData.TryGetValue(owner, out var value))
			{
				value = new ShipData
				{
					pos = position,
					rot = rotation,
					t = Time.time,
					ok = true
				};
				_shipData[owner] = value;
				return;
			}
			float num = Time.time - value.t;
			if (num > 0f)
			{
				value.vel = (position - value.pos) / num;
			}
			value.pos = position;
			value.rot = rotation;
			value.t = Time.time;
			value.ok = true;
		}

		[HarmonyPatch(typeof(Ship), "CustomFixedUpdate")]
		[HarmonyPostfix]
		public static void SmoothShip(Ship __instance)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: 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_0175: 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;
			Vector3 val2 = value.pos + value.vel * Time.deltaTime;
			float num = 0.25f;
			float num2 = 0.15f;
			Player localPlayer = Player.m_localPlayer;
			if (IsPlayerOnShip((localPlayer != null) ? localPlayer.GetPlayerID() : 0))
			{
				num = 0.15f;
				num2 = 0.1f;
			}
			float num3 = Vector3.Distance(((Component)__instance).transform.position, val2);
			if (num3 > 2f)
			{
				transform.position = val2;
				transform.rotation = value.rot;
				return;
			}
			float num4 = Quaternion.Angle(((Component)__instance).transform.rotation, value.rot);
			if (num4 > 15f)
			{
				transform.rotation = value.rot;
			}
			else
			{
				transform.rotation = Quaternion.Slerp(transform.rotation, value.rot, num2);
			}
			transform.position = Vector3.Lerp(transform.position, val2, num);
		}

		[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_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: 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_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: 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_0286: 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;
			}
			bool flag = (Object)(object)val != (Object)(object)shipUnderPlayer;
			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 (flag)
			{
				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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00d2: 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.op_Implicit((Object)(object)value.ship) && !((Character)__instance).IsAttached())
				{
					float num = 15f;
					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.2.7")]
	[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")]
	public class VBNetTweaks : BaseUnityPlugin
	{
		private const string ModName = "VBNetTweaks";

		private const string ModVersion = "0.2.7";

		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> ModuleCompression;

		public static ConfigEntry<bool> EnableClientCompression;

		public static ConfigEntry<bool> ModuleSteamOptimizations;

		public static ConfigEntry<bool> ModuleShipSync;

		public static ConfigEntry<CompressionAlgorithm> m_CompressionAlgorithm;

		public static ConfigEntry<int> CompressionLevel;

		public static ConfigEntry<int> SteamSendRateMinKB;

		public static ConfigEntry<int> SteamSendRateMaxKB;

		public static ConfigEntry<int> SteamSendBufferSize;

		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");
				((MonoBehaviour)this).StartCoroutine(DelayedInit());
				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(StatusEffectVFXFix));
				_harmony.PatchAll(typeof(NetworkSyncPatches));
				_harmony.PatchAll(typeof(ZDONetworkOptimizer));
				((BaseUnityPlugin)this).Logger.LogInfo((object)"VBNetTweaks загружен!");
				if (DebugEnabled.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Режим отладки включен");
				}
			}
		}

		private void Update()
		{
			if (Time.frameCount % 90 == 0)
			{
				StatusEffectVFXManager.Maintenance();
			}
		}

		private IEnumerator DelayedInit()
		{
			yield return (object)new WaitForSeconds(2f);
			if (ModuleCompression.Value)
			{
				ZDONetworkOptimizer.Initialize();
				((MonoBehaviour)this).InvokeRepeating("CheckCompressionStatus", 5f, 30f);
			}
		}

		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, "Включить подробное логирование");
			string text2 = "02 - Modules";
			EnableClientCompression = ((BaseUnityPlugin)this).Config.Bind<bool>(text2, "ClientCompression", true, "Сжимать данные на клиенте (может вызывать проблемы с визуальными эффектами)");
		}

		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);
			ModuleCompression = ConfigFileExtensions.BindConfig<bool>(_serverConfig, text, "Compression", true, "Сжатие сетевого трафика на сервере", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text2 = "03 - Compression Settings";
			m_CompressionAlgorithm = ConfigFileExtensions.BindConfig<CompressionAlgorithm>(_serverConfig, text2, "Algorithm", CompressionAlgorithm.Vanilla, "Алгоритм сжатия: Deflate, Vanilla (встроенная компрессия игры)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ConfigFile serverConfig = _serverConfig;
			AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 9);
			CompressionLevel = ConfigFileExtensions.BindConfig<int>(serverConfig, text2, "Level", 3, "Уровень сжатия (1-9 для Deflate)", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text3 = "04 - Steam Settings";
			SteamSendRateMinKB = ConfigFileExtensions.BindConfig<int>(_serverConfig, text3, "MinRateKB", 256, "Минимальная скорость Steam (vanilla = 150 Kb/s)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			SteamSendRateMaxKB = ConfigFileExtensions.BindConfig<int>(_serverConfig, text3, "MaxRateKB", 4096, "Максимальная скорость Steam (vanilla = 150 Kb/s)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			SteamSendBufferSize = ConfigFileExtensions.BindConfig<int>(_serverConfig, text3, "BufferSize", 100000000, "Размер буфера Steam  (vanilla = 260000 B)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text4 = "05 - Server Settings";
			ConfigFile serverConfig2 = _serverConfig;
			val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f);
			SendInterval = ConfigFileExtensions.BindConfig<float>(serverConfig2, text4, "SendInterval", 0.03f, "Интервал отправки данных (vanilla = 0.05)", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ConfigFile serverConfig3 = _serverConfig;
			val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200);
			PeersPerUpdate = ConfigFileExtensions.BindConfig<int>(serverConfig3, text4, "PeersPerUpdate", 30, "Количество пиров за один апдейт (vanilla = 1)", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ZDOQueueLimit = ConfigFileExtensions.BindConfig<int>(_serverConfig, text4, "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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			try
			{
				val.Write(ModEnabled.Value);
				val.Write(ModuleSteamOptimizations.Value);
				val.Write(ModuleShipSync.Value);
				val.Write(ModuleCompression.Value);
				val.Write(CompressionLevel.Value);
				val.Write(SendInterval.Value);
				val.Write(PeersPerUpdate.Value);
				val.Write(ZDOQueueLimit.Value);
				val.Write(EnableClientCompression.Value);
				val.Write((int)m_CompressionAlgorithm.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();
				ModuleCompression.Value = pkg.ReadBool();
				CompressionLevel.Value = pkg.ReadInt();
				SendInterval.Value = pkg.ReadSingle();
				PeersPerUpdate.Value = pkg.ReadInt();
				ZDOQueueLimit.Value = pkg.ReadInt();
				EnableClientCompression.Value = pkg.ReadBool();
				m_CompressionAlgorithm.Value = (CompressionAlgorithm)pkg.ReadInt();
				Debug.Log((object)$"[VBNetTweaks] Server config applied: Algorithm={m_CompressionAlgorithm.Value}, Level={CompressionLevel.Value}");
			}
			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();
			ZDONetworkOptimizer.ReinitializeCompressor();
			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;
			}
			if (CompressionLevel.Value < 1 || CompressionLevel.Value > 9)
			{
				CompressionLevel.Value = 3;
			}
			ZDONetworkOptimizer.ReinitializeCompressor();
		}

		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 int BytesCompressed { get; private set; }

			public static int BytesOriginal { get; private set; }

			public static float AvgCompressionRatio => (BytesOriginal > 0) ? ((float)BytesCompressed / (float)BytesOriginal) : 1f;

			public static bool CompressionActive { get; private set; }

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

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

			public static void RecordCompression(int originalSize, int compressedSize)
			{
				BytesOriginal += originalSize;
				BytesCompressed += compressedSize;
				CompressionActive = true;
			}

			public static void Reset()
			{
				ZdosSent = 0;
				ZdosReceived = 0;
				BytesCompressed = 0;
				BytesOriginal = 0;
				CompressionActive = false;
			}

			public static string GetStats()
			{
				return $"ZDOs Sent/Recv: {ZdosSent}/{ZdosReceived}, Ratio: {AvgCompressionRatio:P1}";
			}
		}

		private class PeerCompressionStatus
		{
			public int Version { get; set; }

			public bool PeerEnabled { get; set; }

			public bool SendingCompressed { get; set; }

			public bool ReceivingCompressed { get; set; }

			public bool IsCompatible => Version == COMPRESSION_VERSION;
		}

		private static readonly int COMPRESSION_VERSION = 1;

		private const string RPC_VERSION = "VBNT.CompressionVersion";

		private const string RPC_ENABLED = "VBNT.CompressionEnabled";

		private const string RPC_STARTED = "VBNT.CompressionStarted";

		private static bool _firstTickLog = true;

		private static ICompressor _compressor;

		private static bool _serverMode;

		private static readonly Dictionary<ISocket, PeerCompressionStatus> _peerStatus = new Dictionary<ISocket, PeerCompressionStatus>();

		private static float _lastPeerCheck = 0f;

		private const float PEER_CHECK_INTERVAL = 10f;

		private static readonly object _compressorLock = new object();

		public static void CheckAndInitCompression()
		{
			if (!VBNetTweaks.ModuleCompression.Value)
			{
				return;
			}
			if (_compressor == null && VBNetTweaks.ModuleCompression.Value)
			{
				InitCompressor();
			}
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			float time = Time.time;
			if (!(time - _lastPeerCheck > 10f))
			{
				return;
			}
			_lastPeerCheck = time;
			int num = 0;
			int count = _peerStatus.Count;
			foreach (KeyValuePair<ISocket, PeerCompressionStatus> item in _peerStatus)
			{
				if (item.Value.IsCompatible && item.Value.ReceivingCompressed)
				{
					num++;
				}
			}
			if (count > 0 && num == 0 && _compressor != null)
			{
				Helper.LogVerbose($"[Compression] ⚠\ufe0f No compatible peers! Total={count}, Compressor={_compressor.GetType().Name}");
			}
			else if (num > 0 && VBNetTweaks.DebugEnabled.Value)
			{
				Helper.LogDebug($"[Compression] Active: {num}/{count} peers using compression");
			}
		}

		public static string GetCompressionStatus()
		{
			StringBuilder stringBuilder = new StringBuilder();
			string text = ((_compressor != null) ? _compressor.GetType().Name.Replace("Compressor", "") : "NONE");
			stringBuilder.AppendLine(" Active Compressor: " + text);
			string arg = VBNetTweaks.m_CompressionAlgorithm?.Value.ToString() ?? "N/A";
			int num = VBNetTweaks.CompressionLevel?.Value ?? 0;
			stringBuilder.AppendLine($" Config Memory: {arg} (Lvl {num})");
			int count = _peerStatus.Count;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			foreach (PeerCompressionStatus value in _peerStatus.Values)
			{
				if (value.IsCompatible)
				{
					num2++;
				}
				if (value.SendingCompressed)
				{
					num3++;
				}
				if (value.ReceivingCompressed)
				{
					num4++;
				}
			}
			stringBuilder.AppendLine($" Peers: {count} total | {num2} compatible | {num4} receiving");
			float num5 = VBNetTweaks.SendInterval?.Value ?? 0.05f;
			int num6 = VBNetTweaks.PeersPerUpdate?.Value ?? 30;
			int num7 = VBNetTweaks.ZDOQueueLimit?.Value ?? 10240;
			stringBuilder.AppendLine($" ZDO Settings: Interval={num5:F3}s | Batch={num6} | Queue={num7}");
			stringBuilder.AppendLine($" Metrics: {NetworkMetrics.ZdosSent} sent / {NetworkMetrics.ZdosReceived} recv");
			stringBuilder.AppendLine($" Compression Ratio: {NetworkMetrics.AvgCompressionRatio:P1}");
			return stringBuilder.ToString();
		}

		private static void InitCompressor()
		{
			try
			{
				int value = VBNetTweaks.CompressionLevel.Value;
				switch (VBNetTweaks.m_CompressionAlgorithm.Value)
				{
				case CompressionAlgorithm.Deflate:
					_compressor = new DeflateCompressor(value);
					ZLog.LogWarning((object)$"Using Deflate compressor (level {value})");
					break;
				case CompressionAlgorithm.Vanilla:
					_compressor = new VanillaCompressor();
					ZLog.LogWarning((object)"Using Vanilla (native) compressor");
					break;
				}
			}
			catch (Exception ex)
			{
				ZLog.LogError((object)("Compression init failed: " + ex.Message + ", falling back to NO compression"));
				_compressor = null;
			}
		}

		public static void Initialize()
		{
			if (VBNetTweaks.ModuleCompression.Value)
			{
				_serverMode = Helper.IsServer();
				if (_serverMode)
				{
					InitCompressor();
					ZLog.LogWarning((object)"Compression initialized in SERVER mode");
				}
				else if (VBNetTweaks.EnableClientCompression.Value)
				{
					InitCompressor();
					ZLog.LogWarning((object)"Compression initialized in CLIENT mode");
				}
				else
				{
					ZLog.LogWarning((object)"Compression disabled on client");
				}
			}
		}

		public static void ReinitializeCompressor()
		{
			lock (_compressorLock)
			{
				ZLog.LogWarning((object)"[Compression] ===== REINITIALIZING COMPRESSOR =====");
				if (_compressor is IDisposable disposable)
				{
					try
					{
						disposable.Dispose();
					}
					catch
					{
					}
				}
				_compressor = null;
				Dictionary<ISocket, PeerCompressionStatus> dictionary = new Dictionary<ISocket, PeerCompressionStatus>(_peerStatus);
				_peerStatus.Clear();
				if (VBNetTweaks.ModuleCompression.Value)
				{
					InitCompressor();
					foreach (KeyValuePair<ISocket, PeerCompressionStatus> kvp in dictionary)
					{
						PeerCompressionStatus value = new PeerCompressionStatus();
						_peerStatus[kvp.Key] = value;
						if ((Object)(object)ZNet.instance != (Object)null)
						{
							ZNetPeer val = ZNet.instance.GetPeers().Find((ZNetPeer p) => p.m_socket == kvp.Key);
							if (val != null)
							{
								SendCompressionVersion(val);
							}
						}
					}
					ZLog.LogWarning((object)("[Compression] Compressor reinitialized to: " + (_compressor?.GetType().Name ?? "NONE")));
				}
				else
				{
					ZLog.LogWarning((object)"[Compression] Compression disabled after reinitialization");
				}
			}
		}

		public static string GetCurrentCompressorType()
		{
			if (_compressor == null)
			{
				return "NONE";
			}
			string text = _compressor.GetType().Name.Replace("Compressor", "");
			return text.ToLowerInvariant();
		}

		public static bool ShouldCompressSend(ISocket socket)
		{
			if (_serverMode)
			{
				return _compressor != null;
			}
			if (!_peerStatus.TryGetValue(socket, out var value))
			{
				return false;
			}
			return value.SendingCompressed && _compressor != null;
		}

		public static bool ShouldCompressReceive(ISocket socket)
		{
			if (!_peerStatus.TryGetValue(socket, out var value))
			{
				return false;
			}
			if (!_serverMode && value.ReceivingCompressed)
			{
				return true;
			}
			return value.ReceivingCompressed && _compressor != null;
		}

		public static byte[] Compress(byte[] data)
		{
			if (_compressor == null)
			{
				return data;
			}
			try
			{
				byte[] array = _compressor.Compress(data);
				NetworkMetrics.RecordCompression(data.Length, array.Length);
				return array;
			}
			catch (Exception ex)
			{
				ZLog.LogError((object)("Compression failed: " + ex.Message));
				return data;
			}
		}

		public static byte[] Decompress(byte[] data)
		{
			if (_compressor == null)
			{
				return data;
			}
			try
			{
				return _compressor.Decompress(data);
			}
			catch (Exception ex)
			{
				ZLog.LogError((object)("Decompression failed: " + ex.Message));
				return data;
			}
		}

		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;
				if (_firstTickLog)
				{
					_firstTickLog = false;
					ZLog.LogWarning((object)$"[VBNetTweaks] \ufe0f ZDO Tick Started -> Interval: {num:F3}s | Peers/Update: {num3} | ActivePeers: {count}");
				}
				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);
			}
		}

		private static void RegisterCompressionRPCs(ZNetPeer peer)
		{
			peer.m_rpc.Register<int>("VBNT.CompressionVersion", (Action<ZRpc, int>)delegate(ZRpc rpc, int version)
			{
				RPC_CompressionVersion(peer, version);
			});
			peer.m_rpc.Register<bool>("VBNT.CompressionEnabled", (Action<ZRpc, bool>)delegate(ZRpc rpc, bool enabled)
			{
				RPC_CompressionEnabled(peer, enabled);
			});
			peer.m_rpc.Register<bool>("VBNT.CompressionStarted", (Action<ZRpc, bool>)delegate(ZRpc rpc, bool started)
			{
				RPC_CompressionStarted(peer, started);
			});
		}

		private static void SendCompressionVersion(ZNetPeer peer)
		{
			peer.m_rpc.Invoke("VBNT.CompressionVersion", new object[1] { COMPRESSION_VERSION });
		}

		private static void RPC_CompressionVersion(ZNetPeer peer, int version)
		{
			if (_peerStatus.TryGetValue(peer.m_socket, out var value))
			{
				value.Version = version;
				if (value.IsCompatible)
				{
					ZLog.LogWarning((object)("Compression compatible with " + GetPeerName(peer)));
					SendCompressionEnabledStatus(peer);
				}
			}
		}

		private static void SendCompressionEnabledStatus(ZNetPeer peer)
		{
			bool value = VBNetTweaks.ModuleCompression.Value;
			peer.m_rpc.Invoke("VBNT.CompressionEnabled", new object[1] { value });
		}

		private static void RPC_CompressionEnabled(ZNetPeer peer, bool enabled)
		{
			if (_peerStatus.TryGetValue(peer.m_socket, out var value))
			{
				value.PeerEnabled = enabled;
				bool flag = VBNetTweaks.ModuleCompression.Value;
				if (!Helper.IsServer())
				{
					flag = flag && VBNetTweaks.EnableClientCompression.Value;
				}
				flag = flag && enabled && value.IsCompatible;
				SendCompressionStarted(peer, flag);
			}
		}

		private static void SendCompressionStarted(ZNetPeer peer, bool started)
		{
			if (!_peerStatus.TryGetValue(peer.m_socket, out var value) || value.SendingCompressed == started)
			{
				return;
			}
			peer.m_rpc.Invoke("VBNT.CompressionStarted", new object[1] { started });
			Type type = ((object)peer.m_socket).GetType();
			MethodInfo method = type.GetMethod("Flush", Type.EmptyTypes);
			if (method != null && method.DeclaringType != typeof(object))
			{
				try
				{
					peer.m_socket.Flush();
				}
				catch (Exception ex)
				{
					ZLog.LogError((object)("Error flushing socket: " + ex.Message));
				}
			}
			value.SendingCompressed = started;
			ZLog.LogWarning((object)("Compression " + (started ? "started" : "stopped") + " with " + GetPeerName(peer)));
		}

		private static void RPC_CompressionStarted(ZNetPeer peer, bool started)
		{
			if (_peerStatus.TryGetValue(peer.m_socket, out var value))
			{
				value.ReceivingCompressed = started;
				ZLog.LogWarning((object)("Receiving " + (started ? "compressed" : "uncompressed") + " from " + GetPeerName(peer)));
			}
		}

		private static string GetPeerName(ZNetPeer peer)
		{
			try
			{
				ISocket socket = peer.m_socket;
				return ((socket != null) ? socket.GetEndPointString() : null) ?? peer.m_uid.ToString();
			}
			catch
			{
				return peer.m_uid.ToString();
			}
		}

		[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)
		{
			try
			{
				PerformanceMonitor.Track("RemoveObjects", delegate
				{
					if (currentNearObjects != null && currentDistantObjects != null)
					{
						ZDORemoval.OptimizedRemoveObjects(__instance, currentNearObjects, currentDistantObjects);
					}
				});
				return false;
			}
			catch
			{
				return true;
			}
		}

		[HarmonyPatch(typeof(ZNet), "Disconnect")]
		[HarmonyPostfix]
		private static void OnDisconnect(ZNet __instance, ZNetPeer peer)
		{
			_peerStatus.Remove(peer.m_socket);
		}

		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		[HarmonyPostfix]
		private static void OnNewConnection(ZNet __instance, ZNetPeer peer)
		{
			_peerStatus[peer.m_socket] = new PeerCompressionStatus();
			RegisterCompressionRPCs(peer);
			SendCompressionVersion(peer);
		}
	}
	public class ZDORemoval
	{
		public static void OptimizedRemoveObjects(ZNetScene scene, List<ZDO> near, List<ZDO> distant)
		{
			byte b = (byte)((uint)Time.frameCount & 0xFFu);
			foreach (ZDO item in near)
			{
				if (item != null)
				{
					item.TempRemoveEarmark = b;
				}
			}
			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();
			List<ZDO> list = new List<ZDO>(instances.Keys);
			foreach (ZDO item3 in list)
			{
				if (item3 == null || !instances.TryGetValue(item3, out var value) || (Object)(object)value == (Object)null)
				{
					instances.Remove(item3);
				}
				else if (item3.TempRemoveEarmark != b)
				{
					tempRemoved.Add(value);
				}
			}
			foreach (ZNetView item4 in tempRemoved)
			{
				if (Object.op_Implicit((Object)(object)item4))
				{
					ZDO zdo = item4.m_zdo;
					if (zdo != null)
					{
						zdo.Created = false;
						item4.m_zdo = null;
					}
					Object.Destroy((Object)(object)((Component)item4).gameObject);
					instances.Remove(zdo);
				}
			}
		}
	}
}
namespace VBNetTweaks.Utils
{
	[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 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;
		}
	}
	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));
			}
		}

		public static void CheckCompressionStatus()
		{
			if (VBNetTweaks.ModuleCompression.Value && VBNetTweaks.DebugEnabled.Value)
			{
				ZLog.LogWarning((object)ZDONetworkOptimizer.GetCompressionStatus());
			}
		}
	}
}
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(ZDOMan), "SendZDOs")]
		[HarmonyPrefix]
		public static void BeforeSendZDOs(ZDOPeer peer)
		{
			if (VBNetTweaks.DebugEnabled.Value && peer?.m_peer?.m_socket != null && Time.frameCount % 600 == 0)
			{
				string compressionStatus = ZDONetworkOptimizer.GetCompressionStatus();
				ZLog.LogWarning((object)("[Network] Compression status:\n" + compressionStatus));
			}
		}

		[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();
			}
		}
	}
	public static class StatusEffectVFXManager
	{
		private static readonly Dictionary<ZNetView, HashSet<GameObject>> _registry = new Dictionary<ZNetView, HashSet<GameObject>>();

		public static void Register(ZNetView parent, GameObject vfx)
		{
			if (Object.op_Implicit((Object)(object)parent) && Object.op_Implicit((Object)(object)vfx))
			{
				if (!_registry.TryGetValue(parent, out var value))
				{
					value = new HashSet<GameObject>();
					_registry[parent] = value;
				}
				value.Add(vfx);
			}
		}

		public static void Unregister(ZNetView parent, GameObject vfx)
		{
			if (Object.op_Implicit((Object)(object)parent) && _registry.TryGetValue(parent, out var value))
			{
				value.Remove(vfx);
				if (value.Count == 0)
				{
					_registry.Remove(parent);
				}
			}
		}

		public static void CleanupByParent(ZNetView parent)
		{
			if (!_registry.TryGetValue(parent, out var value))
			{
				return;
			}
			ZNetView val = default(ZNetView);
			foreach (GameObject item in value)
			{
				if (!Object.op_Implicit((Object)(object)item))
				{
					continue;
				}
				if (item.TryGetComponent<ZNetView>(ref val))
				{
					if (val.IsValid())
					{
						val.ClaimOwnership();
					}
					val.Destroy();
				}
				else
				{
					Object.Destroy((Object)(object)item);
				}
			}
			_registry.Remove(parent);
		}

		public static void Maintenance()
		{
			List<ZNetView> list = new List<ZNetView>();
			foreach (KeyValuePair<ZNetView, HashSet<GameObject>> item in _registry)
			{
				item.Value.RemoveWhere((GameObject g) => !Object.op_Implicit((Object)(object)g));
				if (item.Value.Count == 0)
				{
					list.Add(item.Key);
				}
			}
			foreach (ZNetView item2 in list)
			{
				_registry.Remove(item2);
			}
		}
	}
	[HarmonyPatch]
	public static class StatusEffectVFXFix
	{
		[HarmonyPatch(typeof(StatusEffect), "TriggerStartEffects")]
		[HarmonyPostfix]
		public static void TrackVFX_Postfix(StatusEffect __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance?.m_character) || __instance.m_startEffectInstances == null)
			{
				return;
			}
			ZNetView component = ((Component)__instance.m_character).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			GameObject[] startEffectInstances = __instance.m_startEffectInstances;
			foreach (GameObject val in startEffectInstances)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					StatusEffectVFXManager.Register(component, val);
				}
			}
		}

		[HarmonyPatch(typeof(StatusEffect), "RemoveStartEffects")]
		[HarmonyPrefix]
		public static bool RemoveVFX_Prefix(StatusEffect __instance)
		{
			if (__instance.m_startEffectInstances == null || !Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return true;
			}
			Character character = __instance.m_character;
			ZNetView parent = ((character != null) ? ((Component)character).GetComponent<ZNetView>() : null);
			GameObject[] startEffectInstances = __instance.m_startEffectInstances;
			ZNetView val2 = default(ZNetView);
			foreach (GameObject val in startEffectInstances)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				StatusEffectVFXManager.Unregister(parent, val);
				if (val.TryGetComponent<ZNetView>(ref val2))
				{
					if (val2.IsValid())
					{
						val2.ClaimOwnership();
					}
					val2.Destroy();
				}
				else
				{
					Object.Destroy((Object)(object)val);
				}
			}
			__instance.m_startEffectInstances = null;
			return false;
		}

		[HarmonyPatch(typeof(ZNetView), "OnDestroy")]
		[HarmonyPostfix]
		public static void ZNetView_OnDestroy_Postfix(ZNetView __instance)
		{
			StatusEffectVFXManager.CleanupByParent(__instance);
		}
	}
	[HarmonyPatch]
	public static class ZSteamSocket_Patchs
	{
		private static bool _isPatched;

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")]
		private static IEnumerable<CodeInstruction> ZSteamSocket_RegisterGlobalCallbacks_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			if (_isPatched)
			{
				return instructions;
			}
			ZLog.LogWarning((object)"[VBNetTweaks] Transpiler entered for ZSteamSocket.RegisterGlobalCallbacks");
			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 = 50000000;
					list[i].operand = num;
					flag = true;
					ZLog.LogWarning((object)$"[VBNetTweaks] Steam transfer rate patched: 153600 -> {num}");
					break;
				}
			}
			if (!flag)
			{
				ZLog.LogWarning((object)"[VBNetTweaks] WARNING: Steam transfer rate constant 153600 NOT FOUND in IL!");
			}
			_isPatched = true;
			return list;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")]
		private static void ZSteamSocket_RegisterGlobalCallbacks_Postfix()
		{
			try
			{
				ZLog.LogWarning((object)"[VBNetTweaks] Applying Steam Socket Settings via Postfix...");
				Type typeFromHandle = typeof(SteamNetworkingUtils);
				if (typeFromHandle == null)
				{
					ZLog.LogError((object)"[VBNetTweaks] SteamNetworkingUtils type not found!");
					return;
				}
				MethodInfo setCfg = typeFromHandle.GetMethod("SetConfigValue", new Type[5]
				{
					typeof(ESteamNetworkingConfigValue),
					typeof(ESteamNetworkingConfigScope),
					typeof(IntPtr),
					typeof(ESteamNetworkingConfigDataType),
					typeof(IntPtr)
				});
				if (setCfg == null)
				{
					ZLog.LogError((object)"[VBNetTweaks] SetConfigValue method not found!");
					return;
				}
				int num = Math.Max(64, VBNetTweaks.SteamSendRateMinKB.Value) * 1024;
				int num2 = Math.Max(num, VBNetTweaks.SteamSendRateMaxKB.Value) * 1024;
				int num3 = Math.Max(8388608, VBNetTweaks.SteamSendBufferSize.Value);
				SetInt((ESteamNetworkingConfigValue)10, num);
				SetInt((ESteamNetworkingConfigValue)11, num2);
				SetInt((ESteamNetworkingConfigValue)9, num3);
				ZLog.LogWarning((object)$"[VBNetTweaks] Steam send rates applied: min={num / 1024}KB/s, max={num2 / 1024}KB/s, buffer={num3 / 1024 / 1024}MB");
				void SetInt(ESteamNetworkingConfigValue key, int value)
				{
					//IL_001e: Unknown result type (might be due to invalid IL or missing references)
					GCHandle gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned);
					try
					{
						setCfg.Invoke(null, new object[5]
						{
							key,
							(object)(ESteamNetworkingConfigScope)1,
							IntPtr.Zero,
							(object)(ESteamNetworkingConfigDataType)1,
							gCHandle.AddrOfPinnedObject()
						});
					}
					finally
					{
						gCHandle.Free();
					}
				}
			}
			catch (Exception ex)
			{
				ZLog.LogError((object)("[VBNetTweaks] Error applying Steam send rates: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}
	[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))
			{
				if (VBNetTweaks.ModuleCompression.Value)
				{
					ZDONetworkOptimizer.CheckAndInitCompression();
				}
				PerformanceMonitor.Track("ZNet.Update", delegate
				{
				});
			}
		}
	}
}
namespace VBNetTweaks.CompressionUtills
{
	public enum CompressionAlgorithm
	{
		Deflate,
		Vanilla
	}
	public interface ICompressor
	{
		byte[] Compress(byte[] data);

		byte[] Decompress(byte[] data);
	}
	public class VanillaCompressor : ICompressor
	{
		public byte[] Compress(byte[] data)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			if (data.Length < 32)
			{
				return data;
			}
			try
			{
				ZPackage val = new ZPackage(data);
				ZPackage val2 = new ZPackage();
				val2.WriteCompressed(val);
				byte[] array = val2.GetArray();
				if (array.Length > 4)
				{
					byte[] array2 = new byte[array.Length - 4];
					Buffer.BlockCopy(array, 4, array2, 0, array2.Length);
					return (array2.Length < data.Length) ? array2 : data;
				}
				return data;
			}
			catch
			{
				return data;
			}
		}

		public byte[] Decompress(byte[] data)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			try
			{
				ZPackage val = new ZPackage();
				byte[] array = new byte[data.Length + 4];
				byte[] bytes = BitConverter.GetBytes(data.Length);
				Buffer.BlockCopy(bytes, 0, array, 0, 4);
				Buffer.BlockCopy(data, 0, array, 4, data.Length);
				val.Load(array);
				return val.ReadCompressedPackage().GetArray();
			}
			catch
			{
				return data;
			}
		}
	}
	public class DeflateCompressor : ICompressor
	{
		private readonly int _level;

		private readonly object _lock = new object();

		public DeflateCompressor(int level)
		{
			_level = Math.Max(1, Math.Min(9, level));
			ZLog.LogWarning((object)$"[Deflate] Compressor created with level {_level}");
		}

		public byte[] Compress(byte[] data)
		{
			if (data.Length < 32)
			{
				return data;
			}
			try
			{
				using MemoryStream memoryStream = new MemoryStream();
				using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionLevel.Fastest))
				{
					deflateStream.Write(data, 0, data.Length);
				}
				byte[] array = memoryStream.ToArray();
				float num = (float)array.Length / (float)data.Length;
				if (array.Length < data.Length)
				{
					Helper.LogDebug($"[Deflate] Compressed {data.Length} -> {array.Length} bytes ({num:P1})");
					return array;
				}
				return data;
			}
			catch (Exception ex)
			{
				ZLog.LogError((object)("[Deflate] Compression failed: " + ex.Message));
				return data;
			}
		}

		public byte[] Decompress(byte[] data)
		{
			try
			{
				using MemoryStream stream = new MemoryStream(data);
				using DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress);
				using MemoryStream memoryStream = new MemoryStream();
				deflateStream.CopyTo(memoryStream);
				byte[] array = memoryStream.ToArray();
				Helper.LogDebug($"[Deflate] Decompressed {data.Length} -> {array.Length} bytes");
				return array;
			}
			catch (Exception ex)
			{
				ZLog.LogError((object)("[Deflate] Decompression failed: " + ex.Message));
				return data;
			}
		}
	}
}