Decompiled source of VBNetTweaks v0.3.8

VBNetTweaks.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using VBNetTweaks.Patches;
using VBNetTweaks.RPCUtills;
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]
	[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
{
	[BepInPlugin("VitByr.VBNetTweaks", "VBNetTweaks", "0.3.8")]
	[BepInIncompatibility("CacoFFF.valheim.LeanNet")]
	[BepInIncompatibility("redseiko.valheim.scenic")]
	[BepInIncompatibility("Searica.Valheim.NetworkTweaks")]
	[BepInIncompatibility("Searica.Valheim.OpenSesame")]
	[BepInIncompatibility("org.bepinex.plugins.network")]
	[BepInIncompatibility("CW_Jesse.BetterNetworking")]
	[BepInIncompatibility("com.Fire.FiresGhettoNetworkMod")]
	public class VBNetTweaks : BaseUnityPlugin
	{
		private const string ModName = "VBNetTweaks";

		private const string ModVersion = "0.3.8";

		private const string ModGUID = "VitByr.VBNetTweaks";

		public CustomRPC _configSyncRPC;

		private ConfigFile _serverConfig;

		public static ConfigEntry<bool> ModEnabled;

		public static ConfigEntry<bool> DebugEnabled;

		public static ConfigEntry<bool> VerboseLogging;

		public static ConfigEntry<bool> ModuleSteamOptimizations;

		public static ConfigEntry<bool> ModuleShipSync;

		public static ConfigEntry<bool> ModuleRPCRadiusFiltering;

		public static ConfigEntry<int> SteamSendRateMaxKB;

		public static ConfigEntry<int> SteamSendBufferSizeKB;

		public static ConfigEntry<float> SendInterval;

		public static ConfigEntry<int> PeersPerUpdate;

		public static ConfigEntry<int> ZDOQueueLimit;

		public static ConfigEntry<float> FlushThresholdPercent;

		private Harmony _harmony;

		public static VBNetTweaks Instance { get; private set; }

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

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

		private void InitServerConfigs()
		{
			string text = "02 - Modules";
			ModuleSteamOptimizations = ConfigFileExtensions.BindConfig<bool>(_serverConfig, text, "SteamOptimizations", true, "Оптимизации Steam сокета", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ModuleShipSync = ConfigFileExtensions.BindConfig<bool>(_serverConfig, text, "ShipSync", true, "Синхронизация кораблей", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ModuleRPCRadiusFiltering = ConfigFileExtensions.BindConfig<bool>(_serverConfig, text, "RPCRadiusFiltering", true, "Включить секторную фильтрацию RPC", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text2 = "03 - Steam Settings";
			ConfigFile serverConfig = _serverConfig;
			AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(256, 10240);
			SteamSendRateMaxKB = ConfigFileExtensions.BindConfig<int>(serverConfig, text2, "MaxRateKB", 4096, "Максимальная скорость отправки Steam (vanilla = 150 KB/s)", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ConfigFile serverConfig2 = _serverConfig;
			val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(512, 8192);
			SteamSendBufferSizeKB = ConfigFileExtensions.BindConfig<int>(serverConfig2, text2, "SendBufferSizeKB", 2048, "Размер буфера отправки Steam в KB (vanilla = ~260KB). Рекомендуется 1024-4096", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			string text3 = "04 - Server Settings";
			ConfigFile serverConfig3 = _serverConfig;
			val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f);
			SendInterval = ConfigFileExtensions.BindConfig<float>(serverConfig3, text3, "SendInterval", 0.03f, "Интервал отправки данных (vanilla = 0.05)", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ConfigFile serverConfig4 = _serverConfig;
			val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200);
			PeersPerUpdate = ConfigFileExtensions.BindConfig<int>(serverConfig4, text3, "PeersPerUpdate", 50, "Количество пиров за один апдейт (vanilla = 1). Лучше ставить значение равное максимальному количеству слотов сервера.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ZDOQueueLimit = ConfigFileExtensions.BindConfig<int>(_serverConfig, text3, "ZDOQueueLimit", 30720, "Размер буфера отправки ZDO пакетов (vanilla = 10240 Kb)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ConfigFile serverConfig5 = _serverConfig;
			val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.8f);
			FlushThresholdPercent = ConfigFileExtensions.BindConfig<float>(serverConfig5, text3, "FlushThresholdPercent", 0.35f, "Процент от ZDOQueueLimit для активации flush (0.0-1.0)\n0.1 = редкий flush (экономия трафика, но задержки)\n0.3 = оптимальный баланс (рекомендуется)\n0.5 = частый flush (меньше задержек, больше трафика)", true, (int?)null, val, (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(ModuleRPCRadiusFiltering.Value);
				val.Write(SteamSendRateMaxKB.Value);
				val.Write(SteamSendBufferSizeKB.Value);
				val.Write(SendInterval.Value);
				val.Write(PeersPerUpdate.Value);
				val.Write(ZDOQueueLimit.Value);
				val.Write(FlushThresholdPercent.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();
				ModuleRPCRadiusFiltering.Value = pkg.ReadBool();
				SteamSendRateMaxKB.Value = pkg.ReadInt();
				SteamSendBufferSizeKB.Value = pkg.ReadInt();
				SendInterval.Value = pkg.ReadSingle();
				PeersPerUpdate.Value = pkg.ReadInt();
				ZDOQueueLimit.Value = pkg.ReadInt();
				FlushThresholdPercent.Value = pkg.ReadInt();
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[VBNetTweaks] Error applying config package: " + ex.Message));
			}
		}

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

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

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

		public IEnumerator ApplyServerConfigChanges()
		{
			yield return null;
			if (SendInterval.Value <= 0.001f)
			{
				SendInterval.Value = 0.03f;
			}
			if (PeersPerUpdate.Value <= 0)
			{
				PeersPerUpdate.Value = 30;
			}
			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);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBNetTweaks] Server config broadcast to all clients");
		}

		private void OnDestroy()
		{
			_serverConfig.Save();
			_harmony.UnpatchSelf();
		}
	}
}
namespace VBNetTweaks.ZDOUtills
{
	[HarmonyPatch]
	public static class ZDONetworkOptimizer
	{
		[HarmonyPatch(typeof(ZNetScene), "RemoveObjects")]
		public static class SafeRemoveObjectsPatch
		{
			private static bool Prefix(ZNetScene __instance, List<ZDO> currentNearObjects, List<ZDO> currentDistantObjects)
			{
				if (!VBNetTweaks.ModuleSteamOptimizations.Value)
				{
					return true;
				}
				byte b = (byte)(Time.frameCount & 0xFF);
				if (currentNearObjects != null)
				{
					foreach (ZDO currentNearObject in currentNearObjects)
					{
						if (currentNearObject != null)
						{
							currentNearObject.TempRemoveEarmark = b;
						}
					}
				}
				if (currentDistantObjects != null)
				{
					foreach (ZDO currentDistantObject in currentDistantObjects)
					{
						if (currentDistantObject != null)
						{
							currentDistantObject.TempRemoveEarmark = b;
						}
					}
				}
				__instance.m_tempRemoved.Clear();
				foreach (KeyValuePair<ZDO, ZNetView> instance in __instance.m_instances)
				{
					if (instance.Key != null && Object.op_Implicit((Object)(object)instance.Value) && instance.Key.TempRemoveEarmark != b)
					{
						__instance.m_tempRemoved.Add(instance.Value);
					}
				}
				return true;
			}
		}

		[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)
			});
			val.SetOperandAndAdvance((object)AccessTools.Method(typeof(ZDONetworkOptimizer), "OptimizedSendZDOToPeers", (Type[])null, (Type[])null));
			return val.InstructionEnumeration();
		}

		public static void OptimizedSendZDOToPeers(ZDOMan zdoManager, float dt)
		{
			try
			{
				int count = zdoManager.m_peers.Count;
				if (count <= 0)
				{
					return;
				}
				zdoManager.m_sendTimer += dt;
				float value = VBNetTweaks.SendInterval.Value;
				if (zdoManager.m_sendTimer < value)
				{
					return;
				}
				zdoManager.m_sendTimer = 0f;
				int num = Math.Max(zdoManager.m_nextSendPeer, 0);
				int value2 = VBNetTweaks.PeersPerUpdate.Value;
				int value3 = VBNetTweaks.ZDOQueueLimit.Value;
				float value4 = VBNetTweaks.FlushThresholdPercent.Value;
				int num2 = Mathf.RoundToInt((float)value3 * value4);
				int num3 = 0;
				for (int i = 0; i < Math.Min(value2, count); i++)
				{
					int index = (num + i) % count;
					ZDOPeer val = zdoManager.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();
						if (sendQueueSize > value3)
						{
							num3++;
							continue;
						}
						bool flag = sendQueueSize <= num2;
						zdoManager.SendZDOs(val, flag);
						num3++;
					}
				}
				zdoManager.m_nextSendPeer = (num + num3) % count;
			}
			catch (Exception arg)
			{
				Helper.LogDebug($"[VBNetTweaks] Error in OptimizedSendZDOToPeers: {arg}");
			}
		}
	}
}
namespace VBNetTweaks.RPCUtills
{
	[HarmonyPatch]
	public static class RpcFilter
	{
		private static int[] _rangeLimitedMethodHashes;

		private static bool IsFeatureEnabled
		{
			get
			{
				if (!VBNetTweaks.ModuleRPCRadiusFiltering.Value)
				{
					return false;
				}
				if (ZNet.IsSinglePlayer)
				{
					return false;
				}
				return true;
			}
		}

		private static bool IsDebugMode
		{
			get
			{
				if (!VBNetTweaks.VerboseLogging.Value)
				{
					return false;
				}
				if (Object.op_Implicit((Object)(object)ZoneSystem.instance))
				{
					return ZoneSystem.instance.GetGlobalKey("VBNET_DEBUG_RPC");
				}
				return false;
			}
		}

		private static bool IsRangeLimitedRpc(RoutedRPCData rpcData)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return IsRangeLimitedRpc(rpcData.m_methodHash, rpcData.m_targetZDO);
		}

		private static bool IsRangeLimitedRpc(int methodHash, ZDOID nviewTargetZDOID)
		{
			if (_rangeLimitedMethodHashes == null)
			{
				_rangeLimitedMethodHashes = new int[44]
				{
					StringExtensionMethods.GetStableHashCode("Step"),
					StringExtensionMethods.GetStableHashCode("RPC_DamageText"),
					StringExtensionMethods.GetStableHashCode("RPC_Heal"),
					StringExtensionMethods.GetStableHashCode("RPC_Stagger"),
					StringExtensionMethods.GetStableHashCode("RPC_AddNoise"),
					StringExtensionMethods.GetStableHashCode("RPC_OnTargeted"),
					StringExtensionMethods.GetStableHashCode("RPC_OnDeath"),
					StringExtensionMethods.GetStableHashCode("RPC_UseStamina"),
					StringExtensionMethods.GetStableHashCode("RPC_UseEitr"),
					StringExtensionMethods.GetStableHashCode("RPC_Emote"),
					StringExtensionMethods.GetStableHashCode("RPC_Wakeup"),
					StringExtensionMethods.GetStableHashCode("RPC_Sleep"),
					StringExtensionMethods.GetStableHashCode("RPC_OnNearProjectileHit"),
					StringExtensionMethods.GetStableHashCode("Rudder"),
					StringExtensionMethods.GetStableHashCode("RequestControl"),
					StringExtensionMethods.GetStableHashCode("ReleaseControl"),
					StringExtensionMethods.GetStableHashCode("RPC_Damage"),
					StringExtensionMethods.GetStableHashCode("RPC_CreateFragments"),
					StringExtensionMethods.GetStableHashCode("RPC_SetAreaHealth"),
					StringExtensionMethods.GetStableHashCode("Hit"),
					StringExtensionMethods.GetStableHashCode("Hide"),
					StringExtensionMethods.GetStableHashCode("RPC_Grow"),
					StringExtensionMethods.GetStableHashCode("RPC_Shake"),
					StringExtensionMethods.GetStableHashCode("RPC_Remove"),
					StringExtensionMethods.GetStableHashCode("RPC_Repair"),
					StringExtensionMethods.GetStableHashCode("RPC_HealthChanged"),
					StringExtensionMethods.GetStableHashCode("RPC_ClearCachedSupport"),
					StringExtensionMethods.GetStableHashCode("RPC_SetPicked"),
					StringExtensionMethods.GetStableHashCode("RPC_Pick"),
					StringExtensionMethods.GetStableHashCode("Command"),
					StringExtensionMethods.GetStableHashCode("SetName"),
					StringExtensionMethods.GetStableHashCode("RPC_UnSummon"),
					StringExtensionMethods.GetStableHashCode("AddSaddle"),
					StringExtensionMethods.GetStableHashCode("SetSaddle"),
					StringExtensionMethods.GetStableHashCode("RPC_AddFuel"),
					StringExtensionMethods.GetStableHashCode("RPC_AddFuelAmount"),
					StringExtensionMethods.GetStableHashCode("RPC_SetFuelAmount"),
					StringExtensionMethods.GetStableHashCode("RPC_ToggleOn"),
					StringExtensionMethods.GetStableHashCode("RPC_RemoveDoneItem"),
					StringExtensionMethods.GetStableHashCode("RPC_AddItem"),
					StringExtensionMethods.GetStableHashCode("RPC_SetSlotVisual"),
					StringExtensionMethods.GetStableHashCode("RPC_Shoot"),
					StringExtensionMethods.GetStableHashCode("RPC_OnLegUse"),
					StringExtensionMethods.GetStableHashCode("RPC_SetLoadedVisual")
				};
			}
			if (!((ZDOID)(ref nviewTargetZDOID)).IsNone())
			{
				return true;
			}
			return _rangeLimitedMethodHashes.Contains(methodHash);
		}

		private static bool IsNearby(Vector3 a, Vector3 b)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (Character.InInterior(a) != Character.InInterior(b))
			{
				return false;
			}
			int num = ZoneSystem.instance.m_activeArea + ZoneSystem.instance.m_activeDistantArea;
			float zoneSize = ZoneSystem.instance.m_zoneSize;
			float num2 = zoneSize / 2f;
			float num3 = (float)(num + 1) * zoneSize + num2;
			if (Mathf.Abs(a.x - b.x) <= num3)
			{
				return Mathf.Abs(a.z - b.z) <= num3;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZRoutedRpc), "InvokeRoutedRPC", new Type[]
		{
			typeof(long),
			typeof(ZDOID),
			typeof(string),
			typeof(object[])
		})]
		private static void ZRoutedRpc_InvokeRoutedRpc(ZRoutedRpc __instance, ZDOID targetZDO, ref long targetPeerID, string methodName)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_008e: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if (!IsFeatureEnabled || targetPeerID != ZRoutedRpc.Everybody || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !IsRangeLimitedRpc(StringExtensionMethods.GetStableHashCode(methodName), targetZDO))
			{
				return;
			}
			Vector3 a;
			if (!((ZDOID)(ref targetZDO)).IsNone())
			{
				ZDOMan instance = ZDOMan.instance;
				ZDO val = ((instance != null) ? instance.GetZDO(targetZDO) : null);
				a = ((val != null) ? val.GetPosition() : ((Component)Player.m_localPlayer).transform.position);
			}
			else
			{
				a = ((Component)Player.m_localPlayer).transform.position;
			}
			bool flag = false;
			List<Player> allPlayers = Player.GetAllPlayers();
			foreach (Player item in allPlayers)
			{
				if ((Object)(object)item == (Object)(object)Player.m_localPlayer || !IsNearby(a, ((Component)item).transform.position))
				{
					continue;
				}
				flag = true;
				break;
			}
			if (!flag)
			{
				if (IsDebugMode)
				{
					Helper.LogVerbose("[RPCFilter] Client: No nearby players, sending " + methodName + " only to self");
				}
				targetPeerID = __instance.m_id;
			}
			else if (IsDebugMode)
			{
				Helper.LogVerbose("[RPCFilter] Client: Nearby players found, broadcasting " + methodName);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZRoutedRpc), "RouteRPC")]
		private static void ZRoutedRpc_RouteRPC(ZRoutedRpc __instance, RoutedRPCData rpcData, ref bool __runOriginal)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			//IL_00d3: 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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			if (!IsFeatureEnabled || !__instance.m_server || rpcData.m_targetPeerID != ZRoutedRpc.Everybody || !IsRangeLimitedRpc(rpcData))
			{
				return;
			}
			Vector3? val = null;
			if (!((ZDOID)(ref rpcData.m_targetZDO)).IsNone())
			{
				ZDOMan instance = ZDOMan.instance;
				ZDO val2 = ((instance != null) ? instance.GetZDO(rpcData.m_targetZDO) : null);
				if (val2 != null)
				{
					val = val2.GetPosition();
				}
			}
			if (!val.HasValue)
			{
				ZNetPeer peer = __instance.GetPeer(rpcData.m_senderPeerID);
				if (peer != null)
				{
					val = peer.m_refPos;
				}
			}
			if (!val.HasValue)
			{
				if (IsDebugMode)
				{
					Helper.LogVerbose($"[RPCFilter] Server: No source position for RPC {rpcData.m_methodHash}, skipping filter");
				}
				return;
			}
			__runOriginal = false;
			ZPackage val3 = new ZPackage();
			rpcData.Serialize(val3);
			int num = 0;
			foreach (ZNetPeer peer2 in __instance.m_peers)
			{
				if (peer2 != null && rpcData.m_senderPeerID != peer2.m_uid && peer2.IsReady() && IsNearby(val.Value, peer2.m_refPos))
				{
					peer2.m_rpc.Invoke("RoutedRPC", new object[1] { val3 });
					num++;
				}
			}
			if (IsDebugMode && num < __instance.m_peers.Count - 1)
			{
				Helper.LogVerbose($"[RPCFilter] Server: {rpcData.m_methodHash} sent to {num}/{__instance.m_peers.Count} peers");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZRoutedRpc), "RouteRPC")]
		private static void ZRoutedRpc_RouteRPC_DEBUG(ZRoutedRpc __instance, RoutedRPCData rpcData)
		{
			if (!IsDebugMode || !__instance.m_server || !IsRangeLimitedRpc(rpcData))
			{
				return;
			}
			Helper.LogVerbose($"[RPCFilter] SERVER ROUTE: ID: {__instance.m_id} MsgID: {rpcData.m_msgID} Peers: {__instance.m_peers.Count}");
			Helper.LogVerbose("[RPCFilter] NAME\tID\t\tSendByID\tIsReady");
			foreach (ZNetPeer peer in __instance.m_peers)
			{
				Helper.LogVerbose($"[RPCFilter] {peer.m_playerName}\t{peer.m_uid}\t{peer.m_uid == rpcData.m_senderPeerID}\t\t{peer.IsReady()}");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZRoutedRpc), "HandleRoutedRPC")]
		private static void ZRoutedRpc_HandleRoutedRPC_DEBUG(ZRoutedRpc __instance, RoutedRPCData data)
		{
			if (IsDebugMode && !__instance.m_server && IsRangeLimitedRpc(data))
			{
				Helper.LogVerbose("[RPCFilter] CLIENT HANDLING RPC: " + $"localSession={ZDOMan.GetSessionID()}, " + $"msgID={data.m_msgID}, " + $"sender={data.m_senderPeerID}, " + $"targetPeer={data.m_targetPeerID}, " + $"method={data.m_methodHash}");
			}
		}
	}
}
namespace VBNetTweaks.Patches
{
	[HarmonyPatch]
	public static class NetworkSyncPatches
	{
		private static float _teleportBoostEnd;

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

		[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(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 readonly Dictionary<long, Vector3> _playerPosVelocities = new Dictionary<long, Vector3>();

		private static FieldInfo m_sendRudderTimeField = AccessTools.Field(typeof(Ship), "m_sendRudderTime");

		[HarmonyPatch(typeof(Ship), "ApplyControlls")]
		[HarmonyPostfix]
		private static void FasterRudder(Ship __instance, Vector3 dir)
		{
			if (__instance.m_nview.IsOwner())
			{
				float num = (float)m_sendRudderTimeField.GetValue(__instance);
				if (Time.time - num > 0.05f)
				{
					m_sendRudderTimeField.SetValue(__instance, Time.time);
					__instance.m_nview.InvokeRPC("Rudder", new object[1] { __instance.m_rudderValue });
				}
			}
		}

		[HarmonyPatch(typeof(Ship), "Awake")]
		[HarmonyPostfix]
		public static void EnableShipInterpolation(Ship __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance.m_body))
			{
				__instance.m_body.interpolation = (RigidbodyInterpolation)1;
				__instance.m_body.collisionDetectionMode = (CollisionDetectionMode)2;
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateAttach")]
		[HarmonyPostfix]
		public static void SmoothAttachedPlayer(Player __instance)
		{
			//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_0098: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.m_attached && __instance.m_attachedToShip && Object.op_Implicit((Object)(object)__instance.m_attachPoint))
			{
				long playerID = __instance.GetPlayerID();
				Transform attachPoint = __instance.m_attachPoint;
				Transform transform = ((Component)__instance).transform;
				if (!_playerPosVelocities.ContainsKey(playerID))
				{
					_playerPosVelocities[playerID] = Vector3.zero;
					transform.position = attachPoint.position;
					transform.rotation = attachPoint.rotation;
					return;
				}
				Vector3 position = attachPoint.position;
				Quaternion rotation = attachPoint.rotation;
				float num = 0.08f;
				Vector3 value = _playerPosVelocities[playerID];
				transform.position = Vector3.SmoothDamp(transform.position, position, ref value, num);
				_playerPosVelocities[playerID] = value;
				transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime / 0.1f);
			}
		}

		[HarmonyPatch(typeof(Player), "AttachStop")]
		[HarmonyPrefix]
		public static void ClearCacheOnDetach(Player __instance)
		{
			RemoveFromCache(__instance.GetPlayerID());
		}

		[HarmonyPatch(typeof(Player), "OnDestroy")]
		[HarmonyPrefix]
		public static void ClearCacheOnDestroy(Player __instance)
		{
			RemoveFromCache(__instance.GetPlayerID());
		}

		private static void RemoveFromCache(long id)
		{
			if (_playerPosVelocities.ContainsKey(id))
			{
				_playerPosVelocities.Remove(id);
			}
		}
	}
	[HarmonyPatch(typeof(Ship))]
	public static class ShipWaterDamagePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("UpdateWaterForce")]
		private static bool 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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);
				}
			}
			return false;
		}
	}
	[HarmonyPatch]
	public static class ZSteamSocket_Patchs
	{
		private static bool _steamConfigApplied = false;

		private static bool _steamConfigAttempted = false;

		private static int _cachedSendBuffer = -1;

		private static int _cachedMaxRate = -1;

		private static bool HasSettingsChanged()
		{
			if (!_steamConfigAttempted)
			{
				return true;
			}
			int num = VBNetTweaks.SteamSendBufferSizeKB.Value * 1024;
			int num2 = VBNetTweaks.SteamSendRateMaxKB.Value * 1024;
			return num != _cachedSendBuffer || num2 != _cachedMaxRate;
		}

		private static void UpdateCachedSettings()
		{
			_cachedSendBuffer = VBNetTweaks.SteamSendBufferSizeKB.Value * 1024;
			_cachedMaxRate = VBNetTweaks.SteamSendRateMaxKB.Value * 1024;
			_steamConfigAttempted = true;
		}

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

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

			public float TotalTime;

			public int Count;

			public float LastLogTime;
		}

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

		private const float LOG_INTERVAL = 5f;

		public static void Track(string name, Action action)
		{
			if (!VBNetTweaks.DebugEnabled.Value)
			{
				action();
				return;
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			action();
			stopwatch.Stop();
			if (!_samples.TryGetValue(name, out var value))
			{
				value = new Sample
				{
					Name = name
				};
			}
			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));
			}
		}
	}
}