Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VBNetTweaks v0.4.0
VBNetTweaks.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Steamworks; using UnityEngine; using VBNetTweaks.Patches; using VBNetTweaks.Utils; using VBNetTweaks.ZDOUtills; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("VBNetTweaks")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("VitByr")] [assembly: AssemblyProduct("VBNetTweaks")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("d9c87954-ce20-459d-81ec-96599caed427")] [assembly: AssemblyFileVersion("0.4.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.4.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace VBNetTweaks { [HarmonyPatch] public static class MapPositionSync { private class MapTrackData { public struct Snapshot { public float time; public Vector3 pos; } private readonly List<Snapshot> _snapshots = new List<Snapshot>(); private Vector3 _lastRealPos; private float _lastRealChangeTime; private Vector3 _velocity; private const int MAX_SNAPSHOTS = 30; public void AddSnapshot(float time, Vector3 pos) { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (_snapshots.Count > 0) { Snapshot snapshot = _snapshots[_snapshots.Count - 1]; if (snapshot.pos == pos) { _snapshots[_snapshots.Count - 1] = new Snapshot { time = time, pos = pos }; return; } float num = time - snapshot.time; if (num > 0.05f && num < 5f) { Vector3 val = pos - snapshot.pos; _velocity = Vector3.ClampMagnitude(val / num, 100f); } else { _velocity = Vector3.zero; } } _snapshots.Add(new Snapshot { time = time, pos = pos }); while (_snapshots.Count > 30) { _snapshots.RemoveAt(0); } _lastRealPos = pos; _lastRealChangeTime = time; } public bool TryGetInterpolated(float renderTime, float maxPredictionTime, float maxPredictionSpeed, out Vector3 result) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) result = Vector3.zero; if (_snapshots.Count == 0) { return false; } if (renderTime <= _snapshots[0].time) { result = _snapshots[0].pos; return true; } if (renderTime >= _snapshots[_snapshots.Count - 1].time) { Snapshot snapshot = _snapshots[_snapshots.Count - 1]; float num = renderTime - snapshot.time; if (num > maxPredictionTime) { num = maxPredictionTime; } Vector3 val = _velocity * num; if (((Vector3)(ref val)).magnitude > maxPredictionSpeed * num) { val = ((Vector3)(ref val)).normalized * maxPredictionSpeed * num; } result = snapshot.pos + val; return true; } for (int i = 1; i < _snapshots.Count; i++) { if (renderTime <= _snapshots[i].time) { Snapshot snapshot2 = _snapshots[i - 1]; Snapshot snapshot3 = _snapshots[i]; float num2 = Mathf.InverseLerp(snapshot2.time, snapshot3.time, renderTime); result = Vector3.Lerp(snapshot2.pos, snapshot3.pos, num2); return true; } } result = _snapshots[_snapshots.Count - 1].pos; return true; } } [CompilerGenerated] private static class <>O { public static CoroutineHandler <0>__OnServerReceiveMapPos; public static CoroutineHandler <1>__OnClientReceiveMapPos; } private static CustomRPC _mapPositionRPC; private static float _mapPosTimer; private static readonly Dictionary<ZDOID, MapTrackData> _mapTracks = new Dictionary<ZDOID, MapTrackData>(); public static void Initialize() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if (_mapPositionRPC == null) { NetworkManager instance = NetworkManager.Instance; object obj = <>O.<0>__OnServerReceiveMapPos; if (obj == null) { CoroutineHandler val = OnServerReceiveMapPos; <>O.<0>__OnServerReceiveMapPos = val; obj = (object)val; } object obj2 = <>O.<1>__OnClientReceiveMapPos; if (obj2 == null) { CoroutineHandler val2 = OnClientReceiveMapPos; <>O.<1>__OnClientReceiveMapPos = val2; obj2 = (object)val2; } _mapPositionRPC = instance.AddRPC("VBNet_MapPositions", (CoroutineHandler)obj, (CoroutineHandler)obj2); Helper.LogDebug("[MapPositionSync] RPC initialized"); } } [HarmonyPatch(typeof(ZNet), "Update")] [HarmonyPostfix] private static void ZNet_Update_MapPos(ZNet __instance) { if (VBNetTweaks.c_ModuleMapPositionSync.Value && __instance.IsServer() && _mapPositionRPC != null) { _mapPosTimer += Time.deltaTime; float value = VBNetTweaks.c_MapPositionSendInterval.Value; if (!(_mapPosTimer < value)) { _mapPosTimer = 0f; SendMapPositions(__instance); } } } private static void SendMapPositions(ZNet net) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) List<ZNetPeer> peers = net.GetPeers(); if (peers.Count == 0) { return; } List<(ZDOID, Vector3)> list = new List<(ZDOID, Vector3)>(); foreach (ZNetPeer item in peers) { if (item.IsReady() && item.m_publicRefPos && !((ZDOID)(ref item.m_characterID)).IsNone()) { list.Add((item.m_characterID, item.m_refPos)); } } if (list.Count == 0) { return; } ZPackage val = new ZPackage(); val.Write(list.Count); foreach (var (val2, val3) in list) { val.Write(val2); val.Write(val3); } _mapPositionRPC.SendPackage(ZRoutedRpc.Everybody, val); if (VBNetTweaks.c_VerboseLogging.Value) { Helper.LogVerbose($"[MapPositionSync] Sent {list.Count} positions"); } } private static IEnumerator OnServerReceiveMapPos(long sender, ZPackage pkg) { yield break; } private static IEnumerator OnClientReceiveMapPos(long sender, ZPackage pkg) { if (!VBNetTweaks.c_ModuleMapPositionSync.Value || Helper.IsServer() || (Object)(object)ZNet.instance == (Object)null) { yield break; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer == null || sender != serverPeer.m_uid) { yield break; } try { int count = pkg.ReadInt(); float now = Time.time; for (int i = 0; i < count; i++) { ZDOID id = pkg.ReadZDOID(); Vector3 pos = pkg.ReadVector3(); if (!_mapTracks.TryGetValue(id, out var track)) { track = new MapTrackData(); _mapTracks[id] = track; } track.AddSnapshot(now, pos); track = null; } if (VBNetTweaks.c_VerboseLogging.Value && count > 0) { Helper.LogVerbose($"[MapPositionSync] Received {count} positions"); } } catch (Exception ex) { Helper.LogDebug("[MapPositionSync] Error processing positions: " + ex.Message); } } [HarmonyPatch(typeof(Minimap), "UpdatePlayerPins")] [HarmonyPostfix] private static void Minimap_UpdatePlayerPins_Postfix(Minimap __instance, float dt) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) if (!VBNetTweaks.c_ModuleMapPositionSync.Value || Helper.IsServer() || __instance.m_playerPins == null || __instance.m_tempPlayerInfo == null) { return; } int num = Mathf.Min(__instance.m_playerPins.Count, __instance.m_tempPlayerInfo.Count); if (num == 0) { return; } float renderTime = Time.time - VBNetTweaks.c_MapInterpolationDelay.Value; float value = VBNetTweaks.c_MapMaxPredictionTime.Value; float value2 = VBNetTweaks.c_MapMaxPredictionSpeed.Value; float value3 = VBNetTweaks.c_MapTeleportThreshold.Value; for (int i = 0; i < num; i++) { PinData val = __instance.m_playerPins[i]; PlayerInfo val2 = __instance.m_tempPlayerInfo[i]; if (!val2.m_publicPosition) { continue; } ZDOID characterID = val2.m_characterID; if (((ZDOID)(ref characterID)).IsNone()) { continue; } if (_mapTracks.TryGetValue(characterID, out var value4)) { if (value4.TryGetInterpolated(renderTime, value, value2, out var result)) { val.m_pos = result; } else { val.m_pos = val2.m_position; } } else { val.m_pos = val2.m_position; } } } [HarmonyPatch(typeof(ZNet), "OnDestroy")] [HarmonyPostfix] private static void ClearCache() { _mapTracks.Clear(); } } [BepInPlugin("VitByr.VBNetTweaks", "VBNetTweaks", "0.4.0")] [BepInIncompatibility("CacoFFF.valheim.LeanNet")] [BepInIncompatibility("redseiko.valheim.scenic")] [BepInIncompatibility("Searica.Valheim.NetworkTweaks")] [BepInIncompatibility("Searica.Valheim.OpenSesame")] [BepInIncompatibility("org.bepinex.plugins.network")] [BepInIncompatibility("CW_Jesse.BetterNetworking")] [BepInIncompatibility("com.Fire.FiresGhettoNetworkMod")] [BepInIncompatibility("sighsorry.SkadiNet")] [BepInIncompatibility("redseiko.valheim.returntosender")] [BepInIncompatibility("com.maxsch.valheim.TimeoutLimit")] [BepInIncompatibility("dzk.warheimnetwork")] public class VBNetTweaks : BaseUnityPlugin { private const string ModName = "VBNetTweaks"; private const string ModVersion = "0.4.0"; private const string ModGUID = "VitByr.VBNetTweaks"; public CustomRPC _configSyncRPC; private ConfigFile _clientConfig; public static ManualLogSource Logger; public static ConfigEntry<Language> c_ConfigLanguage; public static ConfigEntry<bool> c_ModEnabled; public static ConfigEntry<bool> c_DebugEnabled; public static ConfigEntry<bool> c_VerboseLogging; public static ConfigEntry<bool> c_ModuleSteamOptimizations; public static ConfigEntry<bool> c_ModuleZDOOptimization; public static ConfigEntry<bool> c_ModuleShipSync; public static ConfigEntry<bool> c_ModuleZSyncTransformOptimization; public static ConfigEntry<bool> c_ModuleMapPositionSync; public static ConfigEntry<int> c_SteamSendRateMaxKB; public static ConfigEntry<int> c_SteamSendBufferSizeKB; public static ConfigEntry<float> c_SteamTimeoutConnected; public static ConfigEntry<float> c_SteamTimeoutKeepalive; public static ConfigEntry<int> c_SteamRecvMaxMessageSize; public static ConfigEntry<int> c_SteamSendRateMaxKB_S; public static ConfigEntry<int> c_SteamSendBufferSizeKB_S; public static ConfigEntry<int> c_ZDOQueueLimit; public static ConfigEntry<float> c_SendInterval_S; public static ConfigEntry<int> c_PeersPerUpdate_S; public static ConfigEntry<int> c_ZDOQueueLimit_S; public static ConfigEntry<float> c_FlushThresholdPercent_S; public static ConfigEntry<float> c_SmoothPosition; public static ConfigEntry<float> c_SmoothRotation; public static ConfigEntry<float> c_MicroThreshold; public static ConfigEntry<float> c_ClientDistanceThreshold; public static ConfigEntry<float> c_TeleportDistanceThreshold; public static ConfigEntry<float> c_TeleportRotationThreshold; public static ConfigEntry<float> c_MapPositionSendInterval; public static ConfigEntry<float> c_MapInterpolationDelay; public static ConfigEntry<float> c_MapMaxPredictionSpeed; public static ConfigEntry<float> c_MapMaxPredictionTime; public static ConfigEntry<float> c_MapTeleportThreshold; private Harmony _harmony; public static VBNetTweaks Instance { get; private set; } private void Awake() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00cb: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; _clientConfig = new ConfigFile(Path.Combine(Paths.ConfigPath, "VitByr/VBNetTweaks/MainConfig.cfg"), true); SynchronizationManager.Instance.RegisterCustomConfig(_clientConfig); InitClientConfigs(); InitServerConfigs(); c_ModEnabled = ConfigFileExtensions.BindConfig<bool>(_clientConfig, "00 - Master", "ModEnabled", true, (c_ConfigLanguage.Value == Language.Russian) ? "Полностью включить/выключить мод VBNetTweaks" : "Completely enable/disable VBNetTweaks mod", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); if (c_ModEnabled.Value) { _configSyncRPC = NetworkManager.Instance.AddRPC("VBNetTweaks_ConfigSync", new CoroutineHandler(OnAdminConfigSync), new CoroutineHandler(OnClientConfigSync)); SynchronizationManager.Instance.AddInitialSynchronization(_configSyncRPC, (Func<ZPackage>)(() => BuildConfigPackage())); CreateConfigWatcher(); _harmony = new Harmony("VitByr.VBNetTweaks"); if (c_ModuleMapPositionSync.Value) { MapPositionSync.Initialize(); _harmony.PatchAll(typeof(MapPositionSync)); } _harmony.PatchAll(typeof(ZSteamSocket_Patchs)); _harmony.PatchAll(typeof(ShipSyncFix)); _harmony.PatchAll(typeof(NetworkSyncPatches)); _harmony.PatchAll(typeof(ZDONetworkOptimizer)); Helper.LogDebug("Режим отладки включен"); } } private void InitClientConfigs() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown string text = "00 - Language"; c_ConfigLanguage = ((BaseUnityPlugin)this).Config.Bind<Language>(text, "Language", Language.Russian, new ConfigDescription("Select interface language / Выберите язык интерфейса\nRequired Restart / Требуется рестарт", (AcceptableValueBase)null, Array.Empty<object>())); string text2 = "01 - Debug"; c_DebugEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>(text2, "DebugEnabled", false, (c_ConfigLanguage.Value == Language.Russian) ? "Включить отладочный вывод" : "Enable debug output"); c_VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>(text2, "VerboseLogging", false, (c_ConfigLanguage.Value == Language.Russian) ? "Включить подробное логирование" : "Enable verbose logging"); string text3 = "02 - Modules"; c_ModuleSteamOptimizations = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "SteamOptimizations", true, (c_ConfigLanguage.Value == Language.Russian) ? "Оптимизации Steam сокета" : "Steam socket optimizations", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_ModuleZDOOptimization = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "ZDOOptimization", true, (c_ConfigLanguage.Value == Language.Russian) ? "Оптимизация ZDO отправок" : "Optimization ZDO sender", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_ModuleShipSync = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "ShipSync", true, (c_ConfigLanguage.Value == Language.Russian) ? "Синхронизация на кораблях" : "On ship synchronization", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_ModuleZSyncTransformOptimization = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "ZSyncTransformOptimization", true, (c_ConfigLanguage.Value == Language.Russian) ? "Оптимизация движения игроков и мобов" : "Optimizing the movement of players and mobs", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_ModuleMapPositionSync = ConfigFileExtensions.BindConfig<bool>(_clientConfig, text3, "MapPositionSync", true, (c_ConfigLanguage.Value == Language.Russian) ? "Включить плавные маркеры игроков на карте\nУлучшает отображение позиций игроков" : "Enable smooth player markers on map\nImproves display of player positions", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); string text4 = "03 - Client Steam Settings"; c_SteamSendRateMaxKB = ConfigFileExtensions.BindConfig<int>(_clientConfig, text4, "MaxRateKB", 2048, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальная скорость отправки Steam (vanilla = 150 KB/s)" : "Maximum Steam send rate (vanilla = 150 KB/s)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_SteamSendBufferSizeKB = ConfigFileExtensions.BindConfig<int>(_clientConfig, text4, "SendBufferSizeKB", 2048, (c_ConfigLanguage.Value == Language.Russian) ? "Размер буфера отправки Steam в KB (vanilla = ~260KB). Рекомендуется 1024-4096" : "Steam send buffer size in KB (vanilla = ~260KB). Recommended 1024-4096", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_SteamTimeoutConnected = ConfigFileExtensions.BindConfig<float>(_clientConfig, text4, "TimeoutConnected", 120000f, (c_ConfigLanguage.Value == Language.Russian) ? "Таймаут соединения Steam (миллисекунды)\nЕсли соединение неактивно дольше этого времени — оно будет разорвано\nvanilla: 30000 (30 секунд), рекомендуется: 60000-180000" : "Steam connection timeout (milliseconds)\nIf connection is idle longer than this — it will be closed\nvanilla: 30000 (30 sec), recommended: 60000-180000", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_SteamTimeoutKeepalive = ConfigFileExtensions.BindConfig<float>(_clientConfig, text4, "TimeoutKeepalive", 30000f, (c_ConfigLanguage.Value == Language.Russian) ? "Интервал Keep-Alive Steam (миллисекунды)\nКак часто отправлять пинг для поддержания соединения\nvanilla: 30000 (30 секунд), рекомендуется: 15000-60000" : "Steam Keep-Alive interval (milliseconds)\nHow often to send ping to keep connection alive\nvanilla: 30000 (30 sec), recommended: 15000-60000", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_SteamRecvMaxMessageSize = ConfigFileExtensions.BindConfig<int>(_clientConfig, text4, "RecvMaxMessageSize", 8, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальный размер принимаемого сообщения Steam (мегабайты)\nБольшие пакеты будут отклонены\nvanilla: ~1-2 MB, рекомендуется: 4-16 MB" : "Maximum Steam receive message size (megabytes)\nLarge packets will be rejected\nvanilla: ~1-2 MB, recommended: 4-16 MB", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); string text5 = "04 - Client ZDO Settings"; c_ZDOQueueLimit = ConfigFileExtensions.BindConfig<int>(_clientConfig, text5, "ZDOQueueLimit", 10240, (c_ConfigLanguage.Value == Language.Russian) ? "Размер буфера отправки ZDO пакетов (vanilla = 10240 байт)" : "ZDO packet send buffer size (vanilla = 10240 bytes)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); string text6 = "05 - Transform Settings"; c_SmoothPosition = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "SmoothPosition", 0.1f, (c_ConfigLanguage.Value == Language.Russian) ? "Сглаживание позиции (выше = плавнее, но больше задержка) (vanilla: 0.20)" : "Position smoothing value (vanilla: 0.20)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_SmoothRotation = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "SmoothRotation", 0.3f, (c_ConfigLanguage.Value == Language.Russian) ? "Значение сглаживания поворота (vanilla: 0.50)" : "Rotation smoothing value (vanilla: 0.50)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_MicroThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "MicroThreshold", 0.002f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог микро-движений (выше = меньше обновлений) (vanilla: 0.001)" : "Micro-movement threshold (vanilla: 0.001)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_ClientDistanceThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "ClientDistanceThreshold", 0.005f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог дистанции для клиентской синхронизации (vanilla: 0.01)" : "Client distance threshold (vanilla: 0.01)", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_TeleportDistanceThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "TeleportDistanceThreshold", 3f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог дистанции для мгновенного телепорта (метры)\nЕсли объект сместился больше этого значения — телепорт без сглаживания\nvanilla: 5, рекомендуется: 5-20" : "Distance threshold for instant teleport (meters)\nIf object moves beyond this value — teleport without smoothing\nvanilla: 5, recommended: 5-20", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_TeleportRotationThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text6, "TeleportRotationThreshold", 35f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог угла для мгновенного телепорта поворота (градусы)\nЕсли объект повернулся больше этого значения — телепорт без сглаживания\nvanilla: 45, рекомендуется: 30-90" : "Angle threshold for instant rotation teleport (degrees)\nIf object rotates beyond this value — teleport without smoothing\nvanilla: 45, recommended: 30-90", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); string text7 = "08 - Map Positions"; c_MapPositionSendInterval = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "SendInterval", 0.5f, (c_ConfigLanguage.Value == Language.Russian) ? "Интервал отправки позиций игроков (сек)\nМеньше = плавнее, но больше трафик\nvanilla: 2.0, рекомендуется: 0.2-0.5" : "Player position send interval (sec)\nLower = smoother, but more traffic\nvanilla: 2.0, recommended: 0.2-0.5", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_MapInterpolationDelay = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "InterpolationDelay", 0.1f, (c_ConfigLanguage.Value == Language.Russian) ? "Задержка интерполяции маркеров (сек)\nМаркеры будут отставать на это значение для плавности" : "Marker interpolation delay (sec)\nMarkers will lag by this value for smoothness", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_MapMaxPredictionSpeed = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "MaxPredictionSpeed", 40f, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальная скорость предсказания движения (м/с)\nОграничивает рывки при экстраполяции" : "Maximum movement prediction speed (m/s)\nLimits jerks during extrapolation", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_MapMaxPredictionTime = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "MaxPredictionTime", 0.05f, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальное время предсказания движения (сек)\nКак долго маркер двигается по инерции" : "Maximum movement prediction time (sec)\nHow long marker moves by inertia", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_MapTeleportThreshold = ConfigFileExtensions.BindConfig<float>(_clientConfig, text7, "TeleportThreshold", 50f, (c_ConfigLanguage.Value == Language.Russian) ? "Порог телепорта для маркеров (метры)\nЕсли игрок сместился дальше — маркер прыгнет мгновенно" : "Teleport threshold for markers (meters)\nIf player moves beyond — marker jumps instantly", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); } private void InitServerConfigs() { string text = "06 - Server Steam Settings"; c_SteamSendRateMaxKB_S = ConfigFileExtensions.BindConfig<int>(_clientConfig, text, "MaxRateKB", 4096, (c_ConfigLanguage.Value == Language.Russian) ? "Максимальная скорость отправки Steam (vanilla = 150 KB/s)" : "Maximum Steam send rate (vanilla = 150 KB/s)", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_SteamSendBufferSizeKB_S = ConfigFileExtensions.BindConfig<int>(_clientConfig, text, "SendBufferSizeKB", 4096, (c_ConfigLanguage.Value == Language.Russian) ? "Размер буфера отправки Steam в KB (vanilla = ~260KB). Рекомендуется 1024-4096" : "Steam send buffer size in KB (vanilla = ~260KB). Recommended 1024-4096", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); string text2 = "07 - Server ZDO Settings"; c_SendInterval_S = ConfigFileExtensions.BindConfig<float>(_clientConfig, text2, "SendInterval", 0.02f, (c_ConfigLanguage.Value == Language.Russian) ? "Интервал отправки данных (vanilla = 0.05)" : "Data send interval (vanilla = 0.05)", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_PeersPerUpdate_S = ConfigFileExtensions.BindConfig<int>(_clientConfig, text2, "PeersPerUpdate", 10, (c_ConfigLanguage.Value == Language.Russian) ? "Количество пиров за один апдейт (vanilla = 1). Лучше ставить значение равное максимальному количеству слотов сервера." : "Peers per update (vanilla = 1). Better set equal to max server slots.", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_ZDOQueueLimit_S = ConfigFileExtensions.BindConfig<int>(_clientConfig, text2, "ZDOQueueLimit", 20480, (c_ConfigLanguage.Value == Language.Russian) ? "Размер буфера отправки ZDO пакетов (vanilla = 10240 байт)" : "ZDO packet send buffer size (vanilla = 10240 bytes)", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); c_FlushThresholdPercent_S = ConfigFileExtensions.BindConfig<float>(_clientConfig, text2, "FlushThresholdPercent", 0.2f, (c_ConfigLanguage.Value == Language.Russian) ? "Процент от ZDOQueueLimit для активации flush (0.0-1.0)\n0.1 = редкий flush (экономия трафика, но задержки)\n0.3 = оптимальный баланс (рекомендуется)\n0.5 = частый flush (меньше задержек, больше трафика)" : "Percentage of ZDOQueueLimit for flush activation (0.0-1.0)\n0.1 = rare flush (traffic saving, but delays)\n0.3 = optimal balance (recommended)\n0.5 = frequent flush (less delays, more traffic)", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); } public ZPackage BuildConfigPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown ZPackage val = new ZPackage(); try { val.Write(c_ModEnabled.Value); val.Write(c_ModuleSteamOptimizations.Value); val.Write(c_ModuleZDOOptimization.Value); val.Write(c_ModuleShipSync.Value); val.Write(c_ModuleZSyncTransformOptimization.Value); val.Write(c_SteamSendRateMaxKB.Value); val.Write(c_SteamSendBufferSizeKB.Value); val.Write(c_SteamTimeoutConnected.Value); val.Write(c_SteamTimeoutKeepalive.Value); val.Write(c_SteamRecvMaxMessageSize.Value); val.Write(c_ZDOQueueLimit.Value); val.Write(c_SmoothPosition.Value); val.Write(c_SmoothRotation.Value); val.Write(c_MicroThreshold.Value); val.Write(c_ClientDistanceThreshold.Value); val.Write(c_TeleportDistanceThreshold.Value); val.Write(c_TeleportRotationThreshold.Value); val.Write(c_MapPositionSendInterval.Value); val.Write(c_MapInterpolationDelay.Value); val.Write(c_MapMaxPredictionSpeed.Value); val.Write(c_MapMaxPredictionTime.Value); val.Write(c_MapTeleportThreshold.Value); } catch (Exception ex) { Helper.LogDebug("Error building config package: " + ex.Message); return new ZPackage(); } return val; } private void ApplyConfigFromPackage(ZPackage pkg) { if (pkg == null || pkg.GetArray().Length == 0) { Helper.LogDebug("Received empty config package"); return; } try { pkg.SetPos(0); c_ModEnabled.Value = pkg.ReadBool(); c_ModuleSteamOptimizations.Value = pkg.ReadBool(); c_ModuleZDOOptimization.Value = pkg.ReadBool(); c_ModuleShipSync.Value = pkg.ReadBool(); c_ModuleZSyncTransformOptimization.Value = pkg.ReadBool(); c_SteamSendRateMaxKB.Value = pkg.ReadInt(); c_SteamSendBufferSizeKB.Value = pkg.ReadInt(); c_SteamTimeoutConnected.Value = pkg.ReadSingle(); c_SteamTimeoutKeepalive.Value = pkg.ReadSingle(); c_SteamRecvMaxMessageSize.Value = pkg.ReadInt(); c_ZDOQueueLimit.Value = pkg.ReadInt(); c_SmoothPosition.Value = pkg.ReadSingle(); c_SmoothRotation.Value = pkg.ReadSingle(); c_MicroThreshold.Value = pkg.ReadSingle(); c_ClientDistanceThreshold.Value = pkg.ReadSingle(); c_TeleportDistanceThreshold.Value = pkg.ReadSingle(); c_TeleportRotationThreshold.Value = pkg.ReadSingle(); c_MapPositionSendInterval.Value = pkg.ReadSingle(); c_MapInterpolationDelay.Value = pkg.ReadSingle(); c_MapMaxPredictionSpeed.Value = pkg.ReadSingle(); c_MapMaxPredictionTime.Value = pkg.ReadSingle(); c_MapTeleportThreshold.Value = pkg.ReadSingle(); } catch (Exception ex) { Helper.LogDebug("Error applying config package: " + ex.Message); } } private IEnumerator OnAdminConfigSync(long sender, ZPackage pkg) { if (!Helper.IsServer()) { yield break; } ZPackage serverConfigPkg = BuildConfigPackage(); byte[] data = serverConfigPkg.GetArray(); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { ZPackage copyPkg = new ZPackage(data); _configSyncRPC.SendPackage(new List<ZNetPeer> { peer }, copyPkg); } Helper.LogDebug("Server config broadcast to all clients"); } public IEnumerator OnClientConfigSync(long sender, ZPackage pkg) { Helper.LogDebug($"Клиент получил конфиг от сервера {sender}"); ApplyConfigFromPackage(pkg); ConfigFileExtensions.SetSaveOnConfigSet(_clientConfig, true); _clientConfig.Save(); yield break; } private void CreateConfigWatcher() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown ConfigFileWatcher val = new ConfigFileWatcher(_clientConfig, 1000L); val.OnConfigFileReloaded += delegate { if (Helper.IsServer()) { Helper.LogDebug("Server config changed, broadcasting to all clients"); ((MonoBehaviour)this).StartCoroutine(ApplyServerConfigChanges()); } }; } public IEnumerator ApplyServerConfigChanges() { yield return null; ZPackage pkg = BuildConfigPackage(); if (pkg.GetArray().Length == 0) { yield break; } byte[] data = pkg.GetArray(); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { ZPackage copyPkg = new ZPackage(data); _configSyncRPC.SendPackage(new List<ZNetPeer> { peer }, copyPkg); } Helper.LogDebug("Server config broadcast to all clients"); } private void OnDestroy() { ConfigFile clientConfig = _clientConfig; if (clientConfig != null) { clientConfig.Save(); } Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } } namespace VBNetTweaks.ZDOUtills { [HarmonyPatch] public static class ZDONetworkOptimizer { private enum SyncPriority : byte { Default, Piece, Creature, Ship, Player } private static Vector3 _currentRefPos; private static readonly Dictionary<int, SyncPriority> _priorityCache = new Dictionary<int, SyncPriority>(); public static int GetSafeQueueLimit() { return Mathf.Clamp(VBNetTweaks.c_ZDOQueueLimit.Value, 8192, 1048576); } [HarmonyPatch(typeof(ZDOMan), "SendZDOToPeers2")] [HarmonyPrefix] private static bool SendZDOToPeers2_Prefix(ZDOMan __instance, float dt) { if (!VBNetTweaks.c_ModuleZDOOptimization.Value) { return true; } OptimizedSendZDOToPeers(__instance, dt); return false; } public static void OptimizedSendZDOToPeers(ZDOMan man, float dt) { try { int count = man.m_peers.Count; if (count == 0) { return; } man.m_sendTimer += dt; float num = Mathf.Clamp(VBNetTweaks.c_SendInterval_S.Value, 0.01f, 0.2f); if (man.m_sendTimer < num) { return; } man.m_sendTimer = 0f; int num2 = Mathf.Clamp(VBNetTweaks.c_PeersPerUpdate_S.Value, 1, count); int num3 = ((man.m_nextSendPeer >= 0) ? man.m_nextSendPeer : 0); int num4 = 0; for (int i = 0; i < num2; i++) { int index = (num3 + i) % count; num4++; ZDOPeer val = man.m_peers[index]; if (val == null) { continue; } ZNetPeer peer = val.m_peer; bool? obj; if (peer == null) { obj = null; } else { ISocket socket = peer.m_socket; obj = ((socket != null) ? new bool?(socket.IsConnected()) : ((bool?)null)); } if (obj == true) { int sendQueueSize = val.m_peer.m_socket.GetSendQueueSize(); int safeQueueLimit = GetSafeQueueLimit(); if (sendQueueSize <= safeQueueLimit) { float num5 = Mathf.Clamp01(VBNetTweaks.c_FlushThresholdPercent_S.Value) * (float)safeQueueLimit; bool flag = (float)sendQueueSize <= num5; man.SendZDOs(val, flag); } } } man.m_nextSendPeer = (num3 + num4) % count; } catch (Exception arg) { Helper.LogDebug($" Error in OptimizedSendZDOToPeers: {arg}"); } } [HarmonyPatch(typeof(ZDOMan), "ServerSortSendZDOS")] [HarmonyPrefix] private static void ServerSortSendZDOS_Prefix(Vector3 refPos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) _currentRefPos = refPos; } [HarmonyPatch(typeof(ZDOMan), "ServerSendCompare")] [HarmonyPrefix] private static bool CustomServerSendCompare(ZDO x, ZDO y, ref int __result) { if (!VBNetTweaks.c_ModuleZDOOptimization.Value) { return true; } if (!ZNet.instance.IsServer()) { return true; } __result = CustomCompare(x, y); return false; } private static int CustomCompare(ZDO x, ZDO y) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected I4, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected I4, but got Unknown if (x == null || y == null) { return 0; } bool flag = (int)x.Type == 1 && x.HasOwner() && x.GetOwner() != ZDOMan.s_compareReceiver; bool flag2 = (int)y.Type == 1 && y.HasOwner() && y.GetOwner() != ZDOMan.s_compareReceiver; if (flag && flag2) { return CompareFloats(x.m_tempSortValue, y.m_tempSortValue); } if (flag != flag2) { return (!flag) ? 1 : (-1); } if (x.Type != y.Type) { return ((int)y.Type).CompareTo((int)x.Type); } SyncPriority priority = GetPriority(x); SyncPriority priority2 = GetPriority(y); if (priority != priority2) { byte b = (byte)priority2; return b.CompareTo((byte)priority); } return CompareFloats(x.m_tempSortValue, y.m_tempSortValue); } private static int CompareFloats(float a, float b) { if (a < b) { return -1; } if (a > b) { return 1; } return 0; } private static SyncPriority GetPriority(ZDO zdo) { int prefab = zdo.GetPrefab(); if (_priorityCache.TryGetValue(prefab, out var value)) { return value; } SyncPriority syncPriority = SyncPriority.Default; if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab); if (Object.op_Implicit((Object)(object)prefab2)) { if (Object.op_Implicit((Object)(object)prefab2.GetComponent<Player>())) { syncPriority = SyncPriority.Player; } else if (Object.op_Implicit((Object)(object)prefab2.GetComponent<Ship>())) { syncPriority = SyncPriority.Ship; } else if (Object.op_Implicit((Object)(object)prefab2.GetComponent<Character>())) { syncPriority = SyncPriority.Creature; } else if (Object.op_Implicit((Object)(object)prefab2.GetComponent<Piece>())) { syncPriority = SyncPriority.Piece; } } } _priorityCache[prefab] = syncPriority; return syncPriority; } } } namespace VBNetTweaks.Utils { public enum Language { Russian, English } public static class SyncTuning { private static int _frame; private static float _smoothPos; private static float _smoothRot; private static float _microThreshold; private static float _clientDistance; private static float _teleportDistance; private static float _teleportRotation; private static void RefreshIfNeeded() { int frameCount = Time.frameCount; if (frameCount != _frame) { _frame = frameCount; _smoothPos = Mathf.Clamp(VBNetTweaks.c_SmoothPosition.Value, 0.01f, 1f); _smoothRot = Mathf.Clamp(VBNetTweaks.c_SmoothRotation.Value, 0.01f, 1f); _microThreshold = Mathf.Clamp(VBNetTweaks.c_MicroThreshold.Value, 0f, 0.05f); _clientDistance = Mathf.Clamp(VBNetTweaks.c_ClientDistanceThreshold.Value, 0f, 0.1f); _teleportDistance = Mathf.Clamp(VBNetTweaks.c_TeleportDistanceThreshold.Value, 1f, 100f); _teleportRotation = Mathf.Clamp(VBNetTweaks.c_TeleportRotationThreshold.Value, 10f, 180f); } } public static float GetSmoothPosition() { RefreshIfNeeded(); return _smoothPos; } public static float GetSmoothRotation() { RefreshIfNeeded(); return _smoothRot; } public static float GetMicroThreshold() { RefreshIfNeeded(); return _microThreshold; } public static float GetClientDistanceThreshold() { RefreshIfNeeded(); return _clientDistance; } public static float GetTeleportDistanceThreshold() { RefreshIfNeeded(); return _teleportDistance; } public static float GetTeleportRotationThreshold() { RefreshIfNeeded(); return _teleportRotation; } } public static class Helper { private static readonly Dictionary<int, bool> _creatureCache = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> _shipCache = new Dictionary<int, bool>(); public static bool IsCreature(ZDO zdo) { int prefab = zdo.GetPrefab(); if (_creatureCache.TryGetValue(prefab, out var value)) { return value; } bool flag = false; if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab); if (Object.op_Implicit((Object)(object)prefab2)) { flag = Object.op_Implicit((Object)(object)prefab2.GetComponent<Humanoid>()); } } _creatureCache[prefab] = flag; return flag; } public static bool IsShip(ZDO zdo) { int prefab = zdo.GetPrefab(); if (_shipCache.TryGetValue(prefab, out var value)) { return value; } bool flag = false; if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab); if (Object.op_Implicit((Object)(object)prefab2)) { flag = Object.op_Implicit((Object)(object)prefab2.GetComponent<Ship>()); } } _shipCache[prefab] = flag; return flag; } public static bool IsServer() { return Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer(); } public static void LogDebug(string message) { if (VBNetTweaks.c_DebugEnabled.Value) { VBNetTweaks.Logger.LogWarning((object)message); } } public static void LogVerbose(string message) { if (VBNetTweaks.c_VerboseLogging.Value) { VBNetTweaks.Logger.LogInfo((object)message); } } } } namespace VBNetTweaks.Patches { [HarmonyPatch] public static class NetworkSyncPatches { private static float _teleportBoostEnd; public static void TriggerTeleportWindow() { _teleportBoostEnd = Time.time + 5f; } public static int GetQueueLimit() { return Mathf.Max(4096, Helper.IsServer() ? VBNetTweaks.c_ZDOQueueLimit_S.Value : VBNetTweaks.c_ZDOQueueLimit.Value); } [HarmonyPatch(typeof(ZSyncTransform), "SyncPosition")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> SyncPosition_Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); MethodInfo operand = AccessTools.Method(typeof(SyncTuning), "GetSmoothPosition", (Type[])null, (Type[])null); MethodInfo operand2 = AccessTools.Method(typeof(SyncTuning), "GetSmoothRotation", (Type[])null, (Type[])null); MethodInfo operand3 = AccessTools.Method(typeof(SyncTuning), "GetMicroThreshold", (Type[])null, (Type[])null); MethodInfo operand4 = AccessTools.Method(typeof(SyncTuning), "GetTeleportDistanceThreshold", (Type[])null, (Type[])null); for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_R4) { float num = (float)list[i].operand; if (Mathf.Approximately(num, 0.2f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand; } else if (Mathf.Approximately(num, 0.5f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand2; } else if (Mathf.Approximately(num, 0.001f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand3; } else if (Mathf.Approximately(num, 5f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand4; } } } return list; } [HarmonyPatch(typeof(ZSyncTransform), "ClientSync")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> ClientSync_Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); MethodInfo operand = AccessTools.Method(typeof(SyncTuning), "GetSmoothPosition", (Type[])null, (Type[])null); MethodInfo operand2 = AccessTools.Method(typeof(SyncTuning), "GetSmoothRotation", (Type[])null, (Type[])null); MethodInfo operand3 = AccessTools.Method(typeof(SyncTuning), "GetMicroThreshold", (Type[])null, (Type[])null); MethodInfo operand4 = AccessTools.Method(typeof(SyncTuning), "GetClientDistanceThreshold", (Type[])null, (Type[])null); MethodInfo operand5 = AccessTools.Method(typeof(SyncTuning), "GetTeleportRotationThreshold", (Type[])null, (Type[])null); for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_R4) { float num = (float)list[i].operand; if (Mathf.Approximately(num, 0.2f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand; } else if (Mathf.Approximately(num, 0.5f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand2; } else if (Mathf.Approximately(num, 0.001f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand3; } else if (Mathf.Approximately(num, 0.01f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand4; } else if (Mathf.Approximately(num, 45f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand5; } } } return list; } [HarmonyPatch(typeof(ZSyncTransform), "OwnerSync")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> OwnerSync_Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); MethodInfo operand = AccessTools.Method(typeof(SyncTuning), "GetMicroThreshold", (Type[])null, (Type[])null); for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_R4 && Mathf.Approximately((float)list[i].operand, 0.001f)) { list[i].opcode = OpCodes.Call; list[i].operand = operand; } } return list; } [HarmonyPatch(typeof(ZDOMan), "SendZDOs")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> SendZDOs_QueueLimitFix(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = 0; MethodInfo operand = AccessTools.Method(typeof(NetworkSyncPatches), "GetQueueLimit", (Type[])null, (Type[])null); for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_I4 && (int)list[i].operand == 10240) { list[i].opcode = OpCodes.Call; list[i].operand = operand; num++; } } if (num < 2) { Helper.LogDebug("ZDOQueueLimit patch failed: found less than 2 instances of 10240!"); } else if (num == 2) { if (Helper.IsServer()) { Helper.LogDebug($"ZDOQueueLimit patch to: {VBNetTweaks.c_ZDOQueueLimit_S.Value}"); } else { Helper.LogDebug($"ZDOQueueLimit patch to: {VBNetTweaks.c_ZDOQueueLimit.Value}"); } } return list; } [HarmonyPatch(typeof(ZNetScene), "InLoadingScreen")] [HarmonyPrefix] public static bool InLoadingScreen_Extend(ref bool __result) { if (Time.time < _teleportBoostEnd) { __result = true; return false; } return true; } [HarmonyPatch(typeof(ZNetScene), "CreateDestroyObjects")] [HarmonyPostfix] public static void CreateDestroyObjects_TriggerTeleport() { Player localPlayer = Player.m_localPlayer; if (localPlayer != null && ((Character)localPlayer).IsTeleporting()) { TriggerTeleportWindow(); } } } public static class ShipSyncFix { private static float _lastDamageLog; [HarmonyPatch(typeof(ShipControlls), "RPC_RequestRespons")] [HarmonyPrefix] public static void OnControlGranted(ShipControlls __instance, long sender, bool granted) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (!granted || !__instance.m_nview.IsValid() || sender != ZNet.GetUID()) { return; } Ship ship = __instance.m_ship; if (!Object.op_Implicit((Object)(object)ship)) { return; } ZNetView nview = ship.m_nview; if (Object.op_Implicit((Object)(object)nview) && nview.IsValid()) { ZDO zDO = nview.GetZDO(); if (zDO != null && zDO.GetOwner() != sender) { zDO.SetOwner(sender); ZDOMan.instance.ForceSendZDO(zDO.m_uid); Helper.LogVerbose($"[ShipOwnership] Player {sender} took ownership of ship"); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Ship), "UpdateWaterForce")] private static bool UpdateWaterForce_Prefix(Ship __instance, ref float depth, ref float time) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) float num = depth - __instance.m_lastDepth; float num2 = time - __instance.m_lastUpdateWaterForceTime; __instance.m_lastDepth = depth; __instance.m_lastUpdateWaterForceTime = time; if (num2 <= 0.001f) { return true; } float num3 = num / num2; if (num3 <= 0f && Mathf.Abs(num3) > __instance.m_minWaterImpactForce && time - __instance.m_lastWaterImpactTime > __instance.m_minWaterImpactInterval) { __instance.m_lastWaterImpactTime = time; __instance.m_waterImpactEffect.Create(((Component)__instance).transform.position, ((Component)__instance).transform.rotation, (Transform)null, 1f, -1); if (__instance.m_nview.IsOwner() && __instance.m_players.Count > 0) { HitData val = new HitData(); val.m_damage.m_blunt = __instance.m_waterImpactDamage; val.m_point = ((Component)__instance).transform.position; val.m_dir = Vector3.up; __instance.m_destructible.Damage(val); if (VBNetTweaks.c_VerboseLogging.Value && Time.time - _lastDamageLog > 5f) { _lastDamageLog = Time.time; float num4 = Mathf.Abs(num3); Helper.LogVerbose($"[Ship] Water impact damage: speed={num4:F2}, threshold={__instance.m_minWaterImpactForce:F2}, players={__instance.m_players.Count}"); } } } return false; } [HarmonyPatch(typeof(Ship), "ApplyControlls")] [HarmonyPrefix] private static bool ApplyControlls_Prefix(Ship __instance, Vector3 dir) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (!VBNetTweaks.c_ModuleShipSync.Value) { return true; } bool flag = (double)dir.z > 0.5; bool flag2 = (double)dir.z < -0.5; if (flag && !__instance.m_forwardPressed) { __instance.Forward(); } if (flag2 && !__instance.m_backwardPressed) { __instance.Backward(); } __instance.m_forwardPressed = flag; __instance.m_backwardPressed = flag2; float fixedDeltaTime = Time.fixedDeltaTime; float num = Mathf.Lerp(0.5f, 1f, Mathf.Abs(__instance.m_rudderValue)); __instance.m_rudder = dir.x * num; __instance.m_rudderValue += __instance.m_rudder * __instance.m_rudderSpeed * fixedDeltaTime; __instance.m_rudderValue = Mathf.Clamp(__instance.m_rudderValue, -1f, 1f); if (Time.time - __instance.m_sendRudderTime > 0.05f) { __instance.m_sendRudderTime = Time.time; __instance.m_nview.InvokeRPC("Rudder", new object[1] { __instance.m_rudderValue }); } return false; } } [HarmonyPatch] public static class ZSteamSocket_Patchs { private static readonly float TIMEOUT_CONNECTED = VBNetTweaks.c_SteamTimeoutConnected.Value; private static readonly float TIMEOUT_KEEPALIVE = VBNetTweaks.c_SteamTimeoutKeepalive.Value; private static readonly int RECV_MAX_MESSAGE_SIZE = VBNetTweaks.c_SteamRecvMaxMessageSize.Value * 1024 * 1024; [HarmonyTranspiler] [HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")] private static IEnumerable<CodeInstruction> RegisterGlobalCallbacks_Transpiler(IEnumerable<CodeInstruction> instructions) { if (!VBNetTweaks.c_ModuleSteamOptimizations.Value) { return instructions; } List<CodeInstruction> list = new List<CodeInstruction>(instructions); bool flag = false; bool flag2 = false; int num = Math.Max(64, Helper.IsServer() ? VBNetTweaks.c_SteamSendRateMaxKB_S.Value : VBNetTweaks.c_SteamSendRateMaxKB.Value) * 1024; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (val.opcode == OpCodes.Ldc_R4 && val.operand is float num2 && Math.Abs(num2 - 30000f) < 0.001f) { list[i].operand = TIMEOUT_CONNECTED; flag = true; Helper.LogDebug($"TimeoutConnected: 30000 -> {TIMEOUT_CONNECTED}"); } if (val.opcode == OpCodes.Ldc_I4 && val.operand is int num3 && num3 == 153600) { list[i].operand = num; flag2 = true; Helper.LogDebug($"SendRate: 153600 -> {num}"); } } if (!flag) { Helper.LogDebug("TimeoutConnected constant 30000 not found!"); } if (!flag2) { Helper.LogDebug("SendRate constant 153600 not found!"); } return list; } [HarmonyPostfix] [HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")] private static void ApplySteamBuffers() { if (!VBNetTweaks.c_ModuleSteamOptimizations.Value) { return; } try { int num = Math.Max(524288, (Helper.IsServer() ? VBNetTweaks.c_SteamSendBufferSizeKB_S.Value : VBNetTweaks.c_SteamSendBufferSizeKB.Value) * 1024); int num2 = Math.Max(64, Helper.IsServer() ? VBNetTweaks.c_SteamSendRateMaxKB_S.Value : VBNetTweaks.c_SteamSendRateMaxKB.Value) * 1024; int value = Math.Max(262144, num2 / 4); SetConfigInt((ESteamNetworkingConfigValue)9, num); Helper.LogDebug($"SendBufferSize: {num / 1024}KB"); SetConfigInt((ESteamNetworkingConfigValue)10, num); Helper.LogDebug($"RecvBufferSize: {num / 1024}KB"); SetConfigInt((ESteamNetworkingConfigValue)12, RECV_MAX_MESSAGE_SIZE); Helper.LogDebug($"RecvMaxMessageSize: {RECV_MAX_MESSAGE_SIZE / 1024 / 1024}MB"); SetConfigFloat((ESteamNetworkingConfigValue)1, TIMEOUT_KEEPALIVE); Helper.LogDebug($"TimeoutKeepAlive: {TIMEOUT_KEEPALIVE}s"); SetConfigInt((ESteamNetworkingConfigValue)10, value); SetConfigInt((ESteamNetworkingConfigValue)11, num2); } catch (Exception ex) { Helper.LogDebug("Failed to apply Steam buffers: " + ex.Message); } } private static void SetConfigInt(ESteamNetworkingConfigValue config, int value) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) try { GCHandle gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned); try { SteamNetworkingUtils.SetConfigValue(config, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle.AddrOfPinnedObject()); } finally { gCHandle.Free(); } } catch (Exception ex) { Helper.LogDebug($"Failed to set int {config}: {ex.Message}"); } } private static void SetConfigFloat(ESteamNetworkingConfigValue config, float value) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) try { GCHandle gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned); try { SteamNetworkingUtils.SetConfigValue(config, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)3, gCHandle.AddrOfPinnedObject()); } finally { gCHandle.Free(); } } catch (Exception ex) { Helper.LogDebug($"Failed to set float {config}: {ex.Message}"); } } } }