using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using VBNetTweaks.Patches; using VBNetTweaks.Utils; using VBNetTweaks.ZDOUtills; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("VBNetTweaks")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("VBNetTweaks")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("d9c87954-ce20-459d-81ec-96599caed427")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.9.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace VBNetTweaks { [HarmonyPatch] public static class ShipSyncSystem { private class ShipData { public Vector3 pos; public Quaternion rot; public Vector3 vel; public float t; public bool ok; public long lastOwner; public float lastUpdateTime; } private class PlayerShipState { public Ship ship; public Vector3 localPos; public Quaternion localRot; public float lastUpdate; } private static readonly Dictionary _shipData; private static readonly Dictionary _playerStates; private static readonly Dictionary _playersOnShip; private static readonly Dictionary _playerShipMap; private const float SMOOTH_POS_ON_SHIP = 0.35f; private const float SMOOTH_ROT_ON_SHIP = 0.25f; private const float SMOOTH_POS_OFF_SHIP = 0.25f; private const float SMOOTH_ROT_OFF_SHIP = 0.15f; private const float CORRECTION_THRESHOLD = 0.5f; private const float ROT_CORRECTION_THRESHOLD = 10f; private const string RPC_SYNC_SHIP = "VBNT.SyncShip"; static ShipSyncSystem() { _shipData = new Dictionary(); _playerStates = new Dictionary(); _playersOnShip = new Dictionary(); _playerShipMap = new Dictionary(); if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register("VBNT.SyncShip", (Action)RPC_SyncShip); } } private static void SyncShip(long playerId, ZDOID shipId) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)ZNet.instance) && ZRoutedRpc.instance != null && playerId != 0) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "VBNT.SyncShip", new object[2] { playerId, shipId }); PlayerCache.UpdatePlayerState(playerId, PlayerCache.IsPlayerAttached(playerId), shipId); } } private static void RPC_SyncShip(long sender, long playerId, ZDOID shipId) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (sender != ZNet.GetUID()) { PlayerCache.UpdatePlayerState(playerId, PlayerCache.IsPlayerAttached(playerId), shipId); } } public static void CleanupPeer(long uid) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) lock (_shipData) { _shipData.Remove(uid); } lock (_playerStates) { if (_playerShipMap.TryGetValue(uid, out var value)) { if (_playersOnShip.TryGetValue(value, out var value2)) { if (value2 <= 1) { _playersOnShip.Remove(value); } else { _playersOnShip[value] = value2 - 1; } } _playerShipMap.Remove(uid); } _playerStates.Remove(uid); } PlayerCache.RemovePlayer(uid); } private static Ship GetShipUnderPlayer(Player p) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null) { return null; } Vector3 val = ((Component)p).transform.position + Vector3.up * 0.2f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.down, ref val2, 2f)) { return ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent(); } return null; } [HarmonyPatch(typeof(ZNetView), "Deserialize")] [HarmonyPostfix] public static void CaptureShipState(ZNetView __instance) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) if (Helper.IsServer() || (Object)(object)__instance == (Object)null) { return; } Ship component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return; } ZDO zDO = __instance.GetZDO(); if (zDO == null || !zDO.IsValid()) { return; } long owner = zDO.GetOwner(); if (owner == 0L || owner == ZNet.GetUID()) { return; } Vector3 position = zDO.GetPosition(); Quaternion rotation = zDO.GetRotation(); float time = Time.time; if (!_shipData.TryGetValue(owner, out var value)) { value = new ShipData { pos = position, rot = rotation, t = time, ok = true, lastOwner = owner, lastUpdateTime = time }; _shipData[owner] = value; return; } if (value.lastOwner != owner) { value.vel = Vector3.zero; value.lastOwner = owner; value.lastUpdateTime = time; } float num = time - value.t; if (num > 0.01f && num < 0.5f) { Vector3 val = (position - value.pos) / num; value.vel = Vector3.Lerp(value.vel, val, 0.3f); } else if (num >= 0.5f) { value.vel = Vector3.zero; } value.pos = position; value.rot = rotation; value.t = time; value.ok = true; } [HarmonyPatch(typeof(Ship), "CustomFixedUpdate")] [HarmonyPostfix] public static void SmoothShip(Ship __instance) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) if (Helper.IsServer()) { return; } ZNetView nview = __instance.m_nview; ZDO val = ((nview != null) ? nview.GetZDO() : null); if (val == null) { return; } long owner = val.GetOwner(); if (owner == 0L || owner == ZNet.GetUID() || !_shipData.TryGetValue(owner, out var value) || !value.ok) { return; } Transform transform = ((Component)__instance).transform; float time = Time.time; float num = Mathf.Min(Time.deltaTime, 0.033f); Vector3 val2 = value.pos + value.vel * num; Vector3 val3 = val2 - transform.position; if (((Vector3)(ref val3)).magnitude > 5f) { val2 = transform.position + ((Vector3)(ref val3)).normalized * 5f; } Player localPlayer = Player.m_localPlayer; bool flag = PlayerCache.IsPlayerOnShip((localPlayer != null) ? localPlayer.GetPlayerID() : 0); float num2 = (flag ? 0.35f : 0.25f); float num3 = (flag ? 0.25f : 0.15f); float num4 = Vector3.Distance(transform.position, val2); if (num4 > 0.5f) { transform.position = val2; transform.rotation = value.rot; return; } float num5 = Quaternion.Angle(transform.rotation, value.rot); if (num5 > 10f) { transform.rotation = value.rot; } else { transform.rotation = Quaternion.Slerp(transform.rotation, value.rot, num3); } transform.position = Vector3.Lerp(transform.position, val2, num2); } [HarmonyPatch(typeof(Player), "Update")] [HarmonyPostfix] public static void TrackLocalPlayer(Player __instance) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } long playerID = __instance.GetPlayerID(); PlayerShipState value; Ship val = (_playerStates.TryGetValue(playerID, out value) ? value.ship : null); Ship shipUnderPlayer = GetShipUnderPlayer(__instance); if ((Object)(object)val == (Object)(object)shipUnderPlayer && Object.op_Implicit((Object)(object)shipUnderPlayer)) { if (_playerStates.TryGetValue(playerID, out var value2)) { value2.localPos = ((Component)shipUnderPlayer).transform.InverseTransformPoint(((Component)__instance).transform.position); value2.localRot = Quaternion.Inverse(((Component)shipUnderPlayer).transform.rotation) * ((Component)__instance).transform.rotation; value2.lastUpdate = Time.time; } return; } if (Object.op_Implicit((Object)(object)val)) { ZNetView nview = val.m_nview; ZDO val2 = ((nview != null) ? nview.GetZDO() : null); if (val2 != null) { ZDOID uid = val2.m_uid; if (_playersOnShip.TryGetValue(uid, out var value3)) { if (value3 <= 1) { _playersOnShip.Remove(uid); } else { _playersOnShip[uid] = value3 - 1; } } } } if (Object.op_Implicit((Object)(object)shipUnderPlayer)) { ZNetView nview2 = shipUnderPlayer.m_nview; ZDO val3 = ((nview2 != null) ? nview2.GetZDO() : null); if (val3 != null) { ZDOID uid2 = val3.m_uid; _playersOnShip[uid2] = ((!_playersOnShip.TryGetValue(uid2, out var value4)) ? 1 : (value4 + 1)); _playerShipMap[playerID] = uid2; } } if (!_playerStates.TryGetValue(playerID, out var value5)) { value5 = new PlayerShipState(); _playerStates[playerID] = value5; } value5.ship = shipUnderPlayer; if (Object.op_Implicit((Object)(object)shipUnderPlayer)) { value5.localPos = ((Component)shipUnderPlayer).transform.InverseTransformPoint(((Component)__instance).transform.position); value5.localRot = Quaternion.Inverse(((Component)shipUnderPlayer).transform.rotation) * ((Component)__instance).transform.rotation; } value5.lastUpdate = Time.time; if ((Object)(object)val != (Object)(object)shipUnderPlayer) { ZDOID? obj; if (shipUnderPlayer == null) { obj = null; } else { ZNetView nview3 = shipUnderPlayer.m_nview; obj = ((nview3 == null) ? null : nview3.GetZDO()?.m_uid); } ZDOID? val4 = obj; ZDOID valueOrDefault = val4.GetValueOrDefault(); SyncShip(playerID, valueOrDefault); } } [HarmonyPatch(typeof(Player), "LateUpdate")] [HarmonyPostfix] public static void LateUpdate_PlayerSync(Player __instance) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)(object)Player.m_localPlayer)) { long playerID = __instance.GetPlayerID(); if (_playerStates.TryGetValue(playerID, out var value) && !((Object)(object)value.ship == (Object)null) && !((Character)__instance).IsAttached()) { float num = 20f; Vector3 val = ((Component)value.ship).transform.TransformPoint(value.localPos); Quaternion val2 = ((Component)value.ship).transform.rotation * value.localRot; ((Component)__instance).transform.position = Vector3.Lerp(((Component)__instance).transform.position, val, Time.deltaTime * num); ((Component)__instance).transform.rotation = Quaternion.Slerp(((Component)__instance).transform.rotation, val2, Time.deltaTime * num); } } } } [BepInPlugin("VitByr.VBNetTweaks", "VBNetTweaks", "0.3.0")] [BepInIncompatibility("CacoFFF.valheim.LeanNet")] [BepInIncompatibility("redseiko.valheim.scenic")] [BepInIncompatibility("Searica.Valheim.NetworkTweaks")] [BepInIncompatibility("Searica.Valheim.OpenSesame")] [BepInIncompatibility("org.bepinex.plugins.network")] [BepInIncompatibility("CW_Jesse.BetterNetworking")] [BepInIncompatibility("com.Fire.FiresGhettoNetworkMod")] public class VBNetTweaks : BaseUnityPlugin { private const string ModName = "VBNetTweaks"; private const string ModVersion = "0.3.0"; private const string ModGUID = "VitByr.VBNetTweaks"; public CustomRPC _configSyncRPC; private ConfigFile _serverConfig; public static ConfigEntry ModEnabled; public static ConfigEntry DebugEnabled; public static ConfigEntry VerboseLogging; public static ConfigEntry ModuleSteamOptimizations; public static ConfigEntry ModuleShipSync; public static ConfigEntry SteamSendRateMaxKB; public static ConfigEntry SteamSendBufferSizeKB; public static ConfigEntry SendInterval; public static ConfigEntry PeersPerUpdate; public static ConfigEntry ZDOQueueLimit; private Harmony _harmony; public static VBNetTweaks Instance { get; private set; } private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00ad: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown _serverConfig = new ConfigFile(Path.Combine(Paths.ConfigPath, "VitByr/VBNetTweaks/ServerConfig.cfg"), true); SynchronizationManager.Instance.RegisterCustomConfig(_serverConfig); Instance = this; ModEnabled = ConfigFileExtensions.BindConfig(_serverConfig, "00 - Master", "ModEnabled", true, "Полностью включить/выключить мод VBNetTweaks", true, (int?)null, (AcceptableValueBase)null, (Action)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)(() => BuildConfigPackage())); CreateConfigWatcher(); _harmony = new Harmony("VitByr.VBNetTweaks"); if (ModuleSteamOptimizations.Value) { _harmony.PatchAll(typeof(ZSteamSocket_Patchs)); } if (ModuleShipSync.Value) { _harmony.PatchAll(typeof(ShipSyncSystem)); } _harmony.PatchAll(typeof(PlayerCache)); _harmony.PatchAll(typeof(ZNet_Paths)); _harmony.PatchAll(typeof(NetworkSyncPatches)); _harmony.PatchAll(typeof(ZDONetworkOptimizer)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"VBNetTweaks загружен!"); if (DebugEnabled.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Режим отладки включен"); } } } private void InitClientConfigs() { string text = "01 - Debug"; DebugEnabled = ((BaseUnityPlugin)this).Config.Bind(text, "DebugEnabled", false, "Включить отладочный вывод"); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind(text, "VerboseLogging", false, "Включить подробное логирование"); } private void InitServerConfigs() { string text = "02 - Modules"; ModuleSteamOptimizations = ConfigFileExtensions.BindConfig(_serverConfig, text, "SteamOptimizations", true, "Оптимизации Steam сокета", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); ModuleShipSync = ConfigFileExtensions.BindConfig(_serverConfig, text, "ShipSync", true, "Синхронизация кораблей", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); string text2 = "04 - Steam Settings"; ConfigFile serverConfig = _serverConfig; AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange(256, 10240); SteamSendRateMaxKB = ConfigFileExtensions.BindConfig(serverConfig, text2, "MaxRateKB", 4096, "Максимальная скорость отправки Steam (vanilla = 150 KB/s)", true, (int?)null, val, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile serverConfig2 = _serverConfig; val = (AcceptableValueBase)(object)new AcceptableValueRange(512, 8192); SteamSendBufferSizeKB = ConfigFileExtensions.BindConfig(serverConfig2, text2, "SendBufferSizeKB", 2048, "Размер буфера отправки Steam в KB (vanilla = ~260KB). Рекомендуется 1024-4096", true, (int?)null, val, (Action)null, (ConfigurationManagerAttributes)null); string text3 = "05 - Server Settings"; ConfigFile serverConfig3 = _serverConfig; val = (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 0.5f); SendInterval = ConfigFileExtensions.BindConfig(serverConfig3, text3, "SendInterval", 0.03f, "Интервал отправки данных (vanilla = 0.05)", true, (int?)null, val, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile serverConfig4 = _serverConfig; val = (AcceptableValueBase)(object)new AcceptableValueRange(1, 200); PeersPerUpdate = ConfigFileExtensions.BindConfig(serverConfig4, text3, "PeersPerUpdate", 30, "Количество пиров за один апдейт (vanilla = 1)", true, (int?)null, val, (Action)null, (ConfigurationManagerAttributes)null); ZDOQueueLimit = ConfigFileExtensions.BindConfig(_serverConfig, text3, "ZDOQueueLimit", 20480, "Размер буфера отправки ZDO пакетов (vanilla = 10240 Kb)", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); } public ZPackage BuildConfigPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown ZPackage val = new ZPackage(); try { val.Write(ModEnabled.Value); val.Write(ModuleSteamOptimizations.Value); val.Write(ModuleShipSync.Value); val.Write(SendInterval.Value); val.Write(PeersPerUpdate.Value); val.Write(ZDOQueueLimit.Value); } catch (Exception ex) { Debug.LogError((object)("[VBNetTweaks] Error building config package: " + ex.Message)); return new ZPackage(); } return val; } private void ApplyConfigFromPackage(ZPackage pkg) { if (pkg == null || pkg.GetArray().Length == 0) { Debug.LogWarning((object)"[VBNetTweaks] Received empty config package"); return; } try { pkg.SetPos(0); ModEnabled.Value = pkg.ReadBool(); ModuleSteamOptimizations.Value = pkg.ReadBool(); ModuleShipSync.Value = pkg.ReadBool(); SendInterval.Value = pkg.ReadSingle(); PeersPerUpdate.Value = pkg.ReadInt(); ZDOQueueLimit.Value = pkg.ReadInt(); } catch (Exception ex) { Debug.LogError((object)("[VBNetTweaks] Error applying config package: " + ex.Message)); } } private IEnumerator OnAdminConfigSync(long sender, ZPackage pkg) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { yield break; } ZPackage serverConfigPkg = BuildConfigPackage(); byte[] data = serverConfigPkg.GetArray(); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { ZPackage copyPkg = new ZPackage(data); _configSyncRPC.SendPackage(new List { peer }, copyPkg); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBNetTweaks] Server config broadcast to all clients"); } public IEnumerator OnClientConfigSync(long sender, ZPackage pkg) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[VBNetTweaks] Клиент получил конфиг от сервера {sender}"); ApplyConfigFromPackage(pkg); ConfigFileExtensions.SetSaveOnConfigSet(_serverConfig, true); _serverConfig.Save(); yield break; } private void CreateConfigWatcher() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown ConfigFileWatcher val = new ConfigFileWatcher(_serverConfig, 1000L); val.OnConfigFileReloaded += delegate { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { Debug.Log((object)"[VBNetTweaks] Server config changed, broadcasting to all clients"); ((MonoBehaviour)this).StartCoroutine(ApplyServerConfigChanges()); } }; } public IEnumerator ApplyServerConfigChanges() { yield return null; ZPackage pkg = BuildConfigPackage(); if (pkg.GetArray().Length != 0) { byte[] data = pkg.GetArray(); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { ZPackage copyPkg = new ZPackage(data); _configSyncRPC.SendPackage(new List { peer }, copyPkg); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VBNetTweaks] Server config broadcast to all clients"); } if (SendInterval.Value <= 0.001f) { SendInterval.Value = 0.03f; } if (PeersPerUpdate.Value <= 0) { PeersPerUpdate.Value = 30; } } private void OnDestroy() { _serverConfig.Save(); _harmony.UnpatchSelf(); } } } namespace VBNetTweaks.ZDOUtills { [HarmonyPatch] public static class ZDONetworkOptimizer { public static class NetworkMetrics { public static int ZdosSent { get; private set; } public static int ZdosReceived { get; private set; } public static void RecordZdoSent() { ZdosSent++; } public static void RecordZdoReceived() { ZdosReceived++; } } public static void OptimizedSendZDOToPeers(ZDOMan zdoManager, float dt) { try { int count = zdoManager.m_peers.Count; if (count <= 0) { return; } ZDOMan obj = zdoManager; obj.m_sendTimer += dt; float num = VBNetTweaks.SendInterval?.Value ?? 0.05f; if (zdoManager.m_sendTimer < num) { return; } zdoManager.m_sendTimer = 0f; int num2 = Mathf.Max(zdoManager.m_nextSendPeer, 0); int num3 = VBNetTweaks.PeersPerUpdate?.Value ?? 40; int num4 = 0; for (int i = 0; i < Mathf.Min(num3, count); i++) { int index = (num2 + i) % count; ZDOPeer peer = zdoManager.m_peers[index]; ZDOPeer obj2 = peer; if (obj2 == null) { continue; } ZNetPeer peer2 = obj2.m_peer; bool? obj3; if (peer2 == null) { obj3 = null; } else { ISocket socket = peer2.m_socket; obj3 = ((socket != null) ? new bool?(socket.IsConnected()) : null); } if (obj3 == true) { PerformanceMonitor.Track("SendZDOs", delegate { zdoManager.SendZDOs(peer, false); NetworkMetrics.RecordZdoSent(); }); num4++; } } zdoManager.m_nextSendPeer = (num2 + num4) % count; } catch (Exception ex) { ZLog.LogError((object)("[VBNetTweaks] ERROR in OptimizedSendZDOToPeers: " + ex.Message)); zdoManager.SendZDOToPeers2(dt); } } [HarmonyTranspiler] [HarmonyPatch(typeof(ZDOMan), "Update")] private static IEnumerable ZDOManUpdateTranspiler(IEnumerable instructions) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).Start(); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(ZDOMan), "SendZDOToPeers2", (Type[])null, (Type[])null), (string)null) }); if (val.IsInvalid) { ZLog.LogError((object)"WARNING: SendZDOToPeers2 not found"); return instructions; } val.SetOperandAndAdvance((object)AccessTools.Method(typeof(ZDONetworkOptimizer), "OptimizedSendZDOToPeers", (Type[])null, (Type[])null)); return val.InstructionEnumeration(); } [HarmonyPrefix] [HarmonyPatch(typeof(ZNetScene), "RemoveObjects")] private static bool RemoveObjectsPrefix(ZNetScene __instance, List currentNearObjects, List currentDistantObjects) { if (!Object.op_Implicit((Object)(object)__instance) || __instance.m_instances == null || __instance.m_tempRemoved == null) { return true; } try { PerformanceMonitor.Track("PrepareRemoval", delegate { ZDORemoval.PrepareRemovalList(__instance, currentNearObjects, currentDistantObjects); }); return true; } catch (Exception ex) { ZLog.LogError((object)("[VBNetTweaks] Error in RemoveObjectsPrefix: " + ex.Message)); return true; } } } public class ZDORemoval { public static void PrepareRemovalList(ZNetScene scene, List near, List distant) { if (!Object.op_Implicit((Object)(object)scene)) { return; } byte b = (byte)((uint)Time.frameCount & 0xFFu); if (near != null) { foreach (ZDO item in near) { if (item != null) { item.TempRemoveEarmark = b; } } } if (distant != null) { foreach (ZDO item2 in distant) { if (item2 != null) { item2.TempRemoveEarmark = b; } } } Dictionary instances = scene.m_instances; List tempRemoved = scene.m_tempRemoved; tempRemoved.Clear(); foreach (KeyValuePair item3 in instances) { ZDO key = item3.Key; ZNetView value = item3.Value; if (key != null && Object.op_Implicit((Object)(object)value) && key.TempRemoveEarmark != b) { tempRemoved.Add(value); } } } } } namespace VBNetTweaks.Patches { [HarmonyPatch] public static class NetworkSyncPatches { private const float SmoothPos = 0.22f; private const float SmoothRot = 0.45f; private const float MicroThreshold = 0.004f; private static bool _loggedSettings; private static float _teleportBoostEnd; public static void TriggerTeleportWindow() { _teleportBoostEnd = Time.time + 5f; } [HarmonyPatch(typeof(ZDOMan), "Update")] [HarmonyPostfix] private static void LogNetworkSettingsOnce() { if (!_loggedSettings && Object.op_Implicit((Object)(object)ZNet.instance)) { _loggedSettings = true; float num = VBNetTweaks.SendInterval?.Value ?? 0.05f; int num2 = VBNetTweaks.PeersPerUpdate?.Value ?? 20; Helper.LogVerbose($"[VBNetTweaks] Network Config Applied -> SendInterval: {num:F3}s ({1f / num:F1}Hz) | PeersPerUpdate: {num2}"); } } [HarmonyPatch(typeof(ZSyncTransform), "SyncPosition")] [HarmonyTranspiler] public static IEnumerable SyncPosition_Transpiler(IEnumerable instructions) { List list = new List(instructions); for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_R4) { float num = (float)list[i].operand; if (Mathf.Approximately(num, 0.2f)) { list[i].operand = 0.22f; } else if (Mathf.Approximately(num, 0.5f)) { list[i].operand = 0.45f; } else if (Mathf.Approximately(num, 0.001f)) { list[i].operand = 0.004f; } } } return list; } [HarmonyPatch(typeof(ZSyncTransform), "ClientSync")] [HarmonyTranspiler] public static IEnumerable ClientSync_Transpiler(IEnumerable instructions) { List list = new List(instructions); for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_R4) { float num = (float)list[i].operand; if (Mathf.Approximately(num, 0.2f)) { list[i].operand = 0.22f; } else if (Mathf.Approximately(num, 0.001f)) { list[i].operand = 0.004f; } else if (Mathf.Approximately(num, 0.01f)) { list[i].operand = 0.005f; } } } return list; } [HarmonyPatch(typeof(ZDOMan), "SendZDOs")] [HarmonyTranspiler] public static IEnumerable SendZDOs_QueueLimitFix(IEnumerable instructions) { List list = new List(instructions); int num = 0; for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_I4 && (int)list[i].operand == 10240) { list[i].operand = VBNetTweaks.ZDOQueueLimit.Value; num++; } } if (num < 2) { ZLog.LogWarning((object)"[VBNetTweaks] ZDOQueueLimit patch failed: found less than 2 instances of 10240!"); } else if (num == 2) { ZLog.LogWarning((object)$"[VBNetTweaks] ZDOQueueLimit patch to: {VBNetTweaks.ZDOQueueLimit.Value}"); } return list; } [HarmonyPatch(typeof(ZSyncTransform), "OwnerSync")] [HarmonyTranspiler] public static IEnumerable OwnerSync_Transpiler(IEnumerable instructions) { List list = new List(instructions); for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_R4 && Mathf.Approximately((float)list[i].operand, 0.001f)) { list[i].operand = 0.004f; } } return list; } [HarmonyPatch(typeof(ZNetScene), "InLoadingScreen")] [HarmonyPrefix] public static bool InLoadingScreen_Extend(ref bool __result) { if (Time.time < _teleportBoostEnd) { __result = true; return false; } return true; } [HarmonyPatch(typeof(ZNetScene), "CreateDestroyObjects")] [HarmonyPostfix] public static void CreateDestroyObjects_TriggerTeleport() { Player localPlayer = Player.m_localPlayer; if (localPlayer != null && ((Character)localPlayer).IsTeleporting()) { TriggerTeleportWindow(); } } } [HarmonyPatch] public static class ZSteamSocket_Patchs { private static bool _steamConfigApplied; private static float _lastApplyTime; private const float REAPPLY_INTERVAL = 30f; [HarmonyTranspiler] [HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")] private static IEnumerable RegisterGlobalCallbacks_Transpiler(IEnumerable instructions) { if (!VBNetTweaks.ModuleSteamOptimizations.Value) { return instructions; } List list = new List(instructions); bool flag = false; for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_I4 && (int)list[i].operand == 153600) { int num = Math.Max(64, VBNetTweaks.SteamSendRateMaxKB.Value) * 1024; list[i].operand = num; flag = true; ZLog.LogWarning((object)$"[VBNetTweaks] Steam rate patched: 153600 -> {num} bytes/s ({VBNetTweaks.SteamSendRateMaxKB.Value}KB/s)"); break; } } if (!flag) { ZLog.LogWarning((object)"[VBNetTweaks] Steam rate constant 153600 not found in IL!"); } return list; } [HarmonyPostfix] [HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")] private static void ApplySteamBuffersViaReflection() { if (!VBNetTweaks.ModuleSteamOptimizations.Value || (Time.time - _lastApplyTime < 30f && _steamConfigApplied)) { return; } _lastApplyTime = Time.time; try { ZLog.LogWarning((object)"[VBNetTweaks] Applying Steam buffer settings via reflection..."); Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type2 = assembly.GetType("Steamworks.SteamNetworkingUtils"); if (type2 != null) { type = type2; break; } type2 = assembly.GetType("Steamworks.SteamGameServerNetworkingUtils"); if (type2 != null) { type = type2; break; } } if (type == null) { ZLog.LogWarning((object)"[VBNetTweaks] SteamNetworkingUtils type not found, buffer settings skipped."); return; } MethodInfo setConfigMethod = type.GetMethod("SetConfigValue", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[5] { typeof(int), typeof(int), typeof(IntPtr), typeof(int), typeof(IntPtr) }, null); if (setConfigMethod == null) { ZLog.LogWarning((object)"[VBNetTweaks] SetConfigValue method not found, buffer settings skipped."); return; } Type configValueType = null; Type type3 = null; Type type4 = null; Assembly[] assemblies2 = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly2 in assemblies2) { if (configValueType == null) { configValueType = assembly2.GetType("Steamworks.ESteamNetworkingConfigValue"); } if (type3 == null) { type3 = assembly2.GetType("Steamworks.ESteamNetworkingConfigScope"); } if (type4 == null) { type4 = assembly2.GetType("Steamworks.ESteamNetworkingConfigDataType"); } if (configValueType != null && type3 != null && type4 != null) { break; } } if (configValueType == null || type3 == null || type4 == null) { ZLog.LogWarning((object)"[VBNetTweaks] Steam enums not found, buffer settings skipped."); return; } object globalScope = Enum.Parse(type3, "k_ESteamNetworkingConfig_Global"); object intDataType = Enum.Parse(type4, "k_ESteamNetworkingConfig_Int32"); int num = Math.Max(524288, VBNetTweaks.SteamSendBufferSizeKB.Value * 1024); SetConfigValue("k_ESteamNetworkingConfig_SendBufferSize", num); SetConfigValue("k_ESteamNetworkingConfig_RecvBufferSize", num); SetConfigValue("k_ESteamNetworkingConfig_RecvMaxMessageSize", 4194304); int num2 = Math.Max(262144, VBNetTweaks.SteamSendRateMaxKB.Value * 1024 / 2); SetConfigValue("k_ESteamNetworkingConfig_SendRateMin", num2); _steamConfigApplied = true; ZLog.LogWarning((object)$"[VBNetTweaks] Steam buffers applied: SendBuffer={num / 1024}KB, MinRate={num2 / 1024}KB/s"); void SetConfigValue(string keyName, int value) { try { object obj = Enum.Parse(configValueType, keyName); GCHandle gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned); try { setConfigMethod.Invoke(null, new object[5] { (int)obj, (int)globalScope, IntPtr.Zero, (int)intDataType, gCHandle.AddrOfPinnedObject() }); } finally { gCHandle.Free(); } } catch (Exception ex2) { ZLog.LogWarning((object)("[VBNetTweaks] Failed to set " + keyName + ": " + ex2.Message)); } } } catch (Exception ex) { ZLog.LogError((object)("[VBNetTweaks] Failed to apply Steam buffer settings: " + ex.Message)); } } } [HarmonyPatch(typeof(ZNet), "Update")] public static class ZNet_Paths { [HarmonyPostfix] public static void Postfix(ZNet __instance) { if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)ZNet.instance)) { PerformanceMonitor.Track("ZNet.Update", delegate { }); } } } } namespace VBNetTweaks.Utils { public static class PerformanceMonitor { private struct Sample { public string Name; public float TotalTime; public int Count; public float LastLogTime; } private static Dictionary _samples = new Dictionary(); private const float LOG_INTERVAL = 5f; public static void Track(string name, Action action) { if (!VBNetTweaks.DebugEnabled.Value) { action(); return; } Stopwatch stopwatch = Stopwatch.StartNew(); action(); stopwatch.Stop(); if (!_samples.TryGetValue(name, out var value)) { Sample sample = default(Sample); sample.Name = name; value = sample; } value.TotalTime += stopwatch.ElapsedMilliseconds; value.Count++; float time = Time.time; if (time - value.LastLogTime > 5f) { float num = value.TotalTime / (float)value.Count; Helper.LogDebug($"{name}: avg={num:F2}ms over {value.Count} samples"); value.TotalTime = 0f; value.Count = 0; value.LastLogTime = time; } _samples[name] = value; } } [HarmonyPatch] public static class PlayerCache { private static List _cachedPlayers = new List(); private static Dictionary _playersById = new Dictionary(); private static Dictionary _playerAttachedState = new Dictionary(); private static Dictionary _playerShipMap = new Dictionary(); private static int _cachedFrame = -1; private static float _cachedTime = -1f; public static List GetAll() { return GetCached(); } public static List GetCurrentFrame() { return GetCached(0f); } public static List GetCached(float maxAgeSeconds = 0.5f) { if (Time.time - _cachedTime > maxAgeSeconds || _cachedFrame != Time.frameCount) { RefreshCache(); _cachedTime = Time.time; _cachedFrame = Time.frameCount; } return _cachedPlayers; } public static Player GetById(long id) { if (_cachedFrame != Time.frameCount) { RefreshCache(); } Player value; return _playersById.TryGetValue(id, out value) ? value : null; } public static bool IsPlayerOnShip(long playerId) { return _playerShipMap.ContainsKey(playerId); } public static bool IsPlayerAttached(long playerId) { bool value; return _playerAttachedState.TryGetValue(playerId, out value) && value; } public static ZDOID GetPlayerShip(long playerId) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) ZDOID value; return (ZDOID)(_playerShipMap.TryGetValue(playerId, out value) ? value : default(ZDOID)); } public static void UpdatePlayerState(long playerId, bool attached, ZDOID shipId) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) _playerAttachedState[playerId] = attached; if (((ZDOID)(ref shipId)).IsNone()) { _playerShipMap.Remove(playerId); } else { _playerShipMap[playerId] = shipId; } } public static void RemovePlayer(long playerId) { _playersById.Remove(playerId); _playerAttachedState.Remove(playerId); _playerShipMap.Remove(playerId); } private static void RefreshCache() { _cachedPlayers.Clear(); _playersById.Clear(); List allPlayers = Player.GetAllPlayers(); _cachedPlayers.AddRange(allPlayers); foreach (Player item in allPlayers) { if (Object.op_Implicit((Object)(object)item)) { long playerID = item.GetPlayerID(); _playersById[playerID] = item; } } ZLog.Log((object)$"PlayerCache refreshed: {_cachedPlayers.Count} players"); } public static void Invalidate() { _cachedFrame = -1; _cachedTime = -1f; } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] [HarmonyPostfix] private static void OnNewConnection(ZNet __instance, ZNetPeer peer) { Invalidate(); } [HarmonyPatch(typeof(ZNet), "Disconnect")] [HarmonyPostfix] private static void OnDisconnect(ZNet __instance, ZNetPeer peer) { Invalidate(); if (peer != null) { RemovePlayer(peer.m_uid); } } [HarmonyPatch(typeof(Player), "AttachStart")] [HarmonyPostfix] private static void OnAttachStart(Player __instance) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) long playerID = __instance.GetPlayerID(); UpdatePlayerState(playerID, attached: true, default(ZDOID)); } [HarmonyPatch(typeof(Player), "AttachStop")] [HarmonyPostfix] private static void OnAttachStop(Player __instance) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) long playerID = __instance.GetPlayerID(); UpdatePlayerState(playerID, attached: false, default(ZDOID)); } } public static class Helper { public static bool IsServer() { return Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer(); } public static ZNet SafeZNetInstance() { return ZNet.instance; } public static void LogErrorWithContext(string module, string message, Exception ex = null) { string text = ((ex != null) ? (" [" + ex.Message + "]") : ""); Debug.LogError((object)("[VBNetTweaks][" + module + "] " + message + text)); } public static bool IsServerInitialized() { return IsServer() && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer(); } public static void LogDebug(string message) { if (VBNetTweaks.DebugEnabled.Value) { Debug.LogWarning((object)("[VBNetTweaks] " + message)); } } public static void LogVerbose(string message) { if (VBNetTweaks.VerboseLogging.Value) { Debug.LogWarning((object)("[VBNetTweaks] " + message)); } } } }