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 BetterNetworking Valheim v1.3.1
plugins\BetterNetworking_Valheim\DIT.BetterNetworking10.dll
Decompiled 2 weeks agousing System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ConditionalConfigSyncAPI; using Costura; using HarmonyLib; using Ionic.Zlib; using Microsoft.CodeAnalysis; using PlayFab.Party; using Steamworks; using UnityEngine; using ZstdSharp; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyMetadata("PluginVersion", "1.3.1")] [assembly: AssemblyCompany("DIT.BetterNetworking10")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.3.1.0")] [assembly: AssemblyInformationalVersion("1.3.1+6e45f3aad5d989a744625d4c33394b14beddc495")] [assembly: AssemblyProduct("DIT.BetterNetworking10")] [assembly: AssemblyTitle("DIT.BetterNetworking10")] [assembly: AssemblyVersion("1.3.1.0")] [module: RefSafetyRules(11)] internal class <Module> { static <Module>() { AssemblyLoader.Attach(); } } 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 ConditionalConfigSyncAPI { public enum SyncMode { AlwaysServerControlled, Conditional, AlwaysClientControlled } public enum RequirementMode { Fixed, Conditional } public sealed class ConfigSync { public const string PluginGuid = "_shudnal.ConditionalConfigSync"; public const string MinimumCcsVersion = "1.0.10"; private static readonly Version MinimumSupportedCcsVersion = new Version("1.0.10"); private const string BridgeTypeName = "ConditionalConfigSync.SoftDependencyBridge"; private const int MinimumBridgeApiVersion = 1; private readonly string _name; private readonly string _displayName; private readonly string _currentVersion; private readonly string _minimumRequiredVersion; private readonly bool _modRequired; private readonly RequirementMode _requirementMode; private readonly bool _allowClientConfigUpdatesWhenUnlocked; private readonly ManualLogSource _logger; private Type _bridgeType; private PropertyInfo _apiVersionProperty; private PropertyInfo _runtimeReadyProperty; private MethodInfo _createConfigSyncMethod; private MethodInfo _registerConfigEntryMethod; private MethodInfo _registerLockingConfigEntryMethod; private object _configSyncInstance; private bool _permanentFailure; private bool _permanentFailureLogged; private string _failureReason; public bool IsAvailable => EnsureBridge() && IsRuntimeReady(); public bool IsActive => _configSyncInstance != null; public string FailureReason => _failureReason; public ConfigSync(string name, string displayName, string currentVersion, string minimumRequiredVersion = null, bool modRequired = false, RequirementMode requirementMode = RequirementMode.Fixed, bool allowClientConfigUpdatesWhenUnlocked = false, ManualLogSource logger = null) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("A stable mod GUID is required.", "name"); } _name = name; _displayName = (string.IsNullOrWhiteSpace(displayName) ? name : displayName); _currentVersion = currentVersion; _minimumRequiredVersion = minimumRequiredVersion; _modRequired = modRequired; _requirementMode = requirementMode; _allowClientConfigUpdatesWhenUnlocked = allowClientConfigUpdatesWhenUnlocked; _logger = logger; } public bool TryActivate() { return EnsureContext(); } public ConfigEntry<T> Bind<T>(ConfigFile configFile, string section, string key, T defaultValue, string description, SyncMode syncMode = SyncMode.Conditional, bool serverControlledByDefault = true) { if (configFile == null) { throw new ArgumentNullException("configFile"); } ConfigEntry<T> val = configFile.Bind<T>(section, key, defaultValue, description); RegisterConfigEntry<T>(val, syncMode, serverControlledByDefault); return val; } public ConfigEntry<T> Bind<T>(ConfigFile configFile, string section, string key, T defaultValue, ConfigDescription description, SyncMode syncMode = SyncMode.Conditional, bool serverControlledByDefault = true) { if (configFile == null) { throw new ArgumentNullException("configFile"); } ConfigEntry<T> val = configFile.Bind<T>(section, key, defaultValue, description); RegisterConfigEntry<T>(val, syncMode, serverControlledByDefault); return val; } public bool RegisterConfigEntry<T>(ConfigEntry<T> entry, SyncMode syncMode = SyncMode.Conditional, bool serverControlledByDefault = true) { if (entry == null) { throw new ArgumentNullException("entry"); } if (!EnsureContext()) { return false; } try { Invoke(_registerConfigEntryMethod, null, new object[4] { _configSyncInstance, entry, syncMode.ToString(), serverControlledByDefault }); return true; } catch (Exception exception) { LogWarning("Failed to register config entry '" + ((ConfigEntryBase)entry).Definition.Section + " -> " + ((ConfigEntryBase)entry).Definition.Key + "' with Conditional Config Sync. The entry remains a normal local BepInEx setting. " + GetInnermostMessage(exception)); return false; } } public bool RegisterLockingConfigEntry<T>(ConfigEntry<T> entry) where T : IConvertible { if (entry == null) { throw new ArgumentNullException("entry"); } if (!EnsureContext()) { return false; } try { Invoke(_registerLockingConfigEntryMethod, null, new object[2] { _configSyncInstance, entry }); return true; } catch (Exception exception) { LogWarning("Failed to register locking config entry '" + ((ConfigEntryBase)entry).Definition.Section + " -> " + ((ConfigEntryBase)entry).Definition.Key + "' with Conditional Config Sync. The entry remains a normal local BepInEx setting. " + GetInnermostMessage(exception)); return false; } } public ConfigEntry<T> BindLocking<T>(ConfigFile configFile, string section, string key, T defaultValue, string description) where T : IConvertible { if (configFile == null) { throw new ArgumentNullException("configFile"); } ConfigEntry<T> val = configFile.Bind<T>(section, key, defaultValue, description); RegisterLockingConfigEntry<T>(val); return val; } public ConfigEntry<T> BindLocking<T>(ConfigFile configFile, string section, string key, T defaultValue, ConfigDescription description) where T : IConvertible { if (configFile == null) { throw new ArgumentNullException("configFile"); } ConfigEntry<T> val = configFile.Bind<T>(section, key, defaultValue, description); RegisterLockingConfigEntry<T>(val); return val; } private bool EnsureContext() { if (_configSyncInstance != null) { return true; } if (_permanentFailure || !EnsureBridge() || !IsRuntimeReady()) { return false; } try { _configSyncInstance = Invoke(_createConfigSyncMethod, null, new object[7] { _name, _displayName, _currentVersion, _minimumRequiredVersion, _modRequired, _requirementMode.ToString(), _allowClientConfigUpdatesWhenUnlocked }); if (_configSyncInstance == null) { SetPermanentFailure("Conditional Config Sync returned no consumer context.", null); return false; } return true; } catch (Exception exception) { SetPermanentFailure("Failed to create the Conditional Config Sync consumer context.", exception); return false; } } private bool EnsureBridge() { if (_bridgeType != null) { return true; } if (_permanentFailure) { return false; } try { if (!Chainloader.PluginInfos.TryGetValue("_shudnal.ConditionalConfigSync", out var value) || value == null || (Object)(object)value.Instance == (Object)null) { return false; } if (value.Metadata == null || value.Metadata.Version == null || value.Metadata.Version.CompareTo(MinimumSupportedCcsVersion) < 0) { return false; } Assembly assembly = ((object)value.Instance).GetType().Assembly; Type type = assembly.GetType("ConditionalConfigSync.SoftDependencyBridge", throwOnError: false); if (type == null) { SetPermanentFailure("The installed Conditional Config Sync version does not expose the optional soft-dependency bridge.", null); return false; } PropertyInfo property = type.GetProperty("ApiVersion", BindingFlags.Static | BindingFlags.Public); PropertyInfo property2 = type.GetProperty("IsRuntimeReady", BindingFlags.Static | BindingFlags.Public); MethodInfo method = type.GetMethod("CreateConfigSync", BindingFlags.Static | BindingFlags.Public, null, new Type[7] { typeof(string), typeof(string), typeof(string), typeof(string), typeof(bool), typeof(string), typeof(bool) }, null); MethodInfo method2 = type.GetMethod("RegisterConfigEntry", BindingFlags.Static | BindingFlags.Public, null, new Type[4] { typeof(object), typeof(ConfigEntryBase), typeof(string), typeof(bool) }, null); MethodInfo method3 = type.GetMethod("RegisterLockingConfigEntry", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(object), typeof(ConfigEntryBase) }, null); if (property == null || property2 == null || method == null || method2 == null || method3 == null) { SetPermanentFailure("The installed Conditional Config Sync soft-dependency bridge is incomplete or incompatible.", null); return false; } if (!(property.GetValue(null, null) is int num) || num < 1) { SetPermanentFailure("The installed Conditional Config Sync soft-dependency bridge version is not supported.", null); return false; } _bridgeType = type; _apiVersionProperty = property; _runtimeReadyProperty = property2; _createConfigSyncMethod = method; _registerConfigEntryMethod = method2; _registerLockingConfigEntryMethod = method3; return true; } catch (Exception exception) { SetPermanentFailure("Failed to resolve the Conditional Config Sync soft-dependency bridge.", exception); return false; } } private bool IsRuntimeReady() { try { object value = _runtimeReadyProperty.GetValue(null, null); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch (Exception exception) { SetPermanentFailure("Failed to query the Conditional Config Sync runtime state.", exception); return false; } } private static object Invoke(MethodInfo method, object target, object[] arguments) { try { return method.Invoke(target, arguments); } catch (TargetInvocationException ex) when (ex.InnerException != null) { ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); throw; } } private void SetPermanentFailure(string message, Exception exception) { _permanentFailure = true; _failureReason = ((exception == null) ? message : (message + " " + GetInnermostMessage(exception))); if (!_permanentFailureLogged) { _permanentFailureLogged = true; LogWarning(_failureReason); } } private void LogWarning(string message) { if (_logger != null) { _logger.LogWarning((object)message); } } private static string GetInnermostMessage(Exception exception) { Exception ex = exception; while (ex.InnerException != null) { ex = ex.InnerException; } return ex.Message; } } } namespace DIT.BetterNetworking10 { [BepInPlugin("DIT.BetterNetworking10", "Better Networking 1.0 Safe", "1.3.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("CW_Jesse.BetterNetworking")] [BepInIncompatibility("org.bepinex.plugins.network")] [BepInIncompatibility("be.sebastienvercammen.valheim.netcompression")] [BepInIncompatibility("com.github.dalayeth.Networkfix")] [BepInIncompatibility("Steel.ValheimMod")] public sealed class BetterNetworking10 : BaseUnityPlugin { public const string PluginGuid = "DIT.BetterNetworking10"; public const string PluginName = "Better Networking 1.0 Safe"; public const string PluginVersion = "1.3.1"; private const string MinimumSyncCompatibleVersion = "1.3.0"; internal static ConfigEntry<bool> LockConfiguration; internal static ConfigEntry<CompatibilityMode> Mode; internal static ConfigEntry<bool> EnableCompression; internal static ConfigEntry<bool> EnableQueueSize; internal static ConfigEntry<bool> EnableUpdateRate; internal static ConfigEntry<bool> EnableSendRate; internal static ConfigEntry<bool> EnableConnectionBuffer; internal static ConfigEntry<bool> EnablePortalGhostFix; internal static ConfigEntry<QueueSizeOption> QueueSize; internal static ConfigEntry<UpdateRateOption> UpdateRate; internal static ConfigEntry<SendRateOption> MinimumSendRate; internal static ConfigEntry<SendRateOption> MaximumSendRate; internal static ConfigEntry<ForceCrossplayOption> ForceCrossplay; internal static ConfigEntry<int> PlayerLimit; private Harmony _harmony; private ConfigSync _configSync; internal static BetterNetworking10 Instance { get; private set; } internal static BNLog Log { get; private set; } internal static bool CompressionRuntimeAvailable { get; set; } internal static bool SafeMode => Mode.Value == CompatibilityMode.VanillaSafe; internal static bool CompressionActive => CompressionRuntimeAvailable && EnableCompression.Value; internal static bool QueueActive => !SafeMode && EnableQueueSize.Value && QueueSize.Value != QueueSizeOption.Vanilla; internal static bool UpdateRateActive => !SafeMode && EnableUpdateRate.Value && UpdateRate.Value != UpdateRateOption.Percent100; internal static bool SendRateActive => !SafeMode && EnableSendRate.Value; internal static bool ConnectionBufferActive => !SafeMode && EnableConnectionBuffer.Value; internal static bool PortalGhostFixActive => EnablePortalGhostFix.Value; internal static int QueueBudgetBytes => QueueSize.Value switch { QueueSizeOption.KB80 => 81920, QueueSizeOption.KB64 => 65536, QueueSizeOption.KB48 => 49152, QueueSizeOption.KB32 => 32768, _ => 10240, }; internal static float UpdateRateMultiplier => UpdateRate.Value switch { UpdateRateOption.Percent75 => 0.75f, UpdateRateOption.Percent50 => 0.5f, _ => 1f, }; internal static bool IsDedicated => ((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.IsDedicated() : Application.isBatchMode; private void Awake() { //IL_0083: 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_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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_0106: Expected O, but got Unknown Instance = this; bool flag = !File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath); _configSync = new ConfigSync("DIT.BetterNetworking10", "Better Networking 1.0 Safe", "1.3.1", "1.3.0", modRequired: false, RequirementMode.Conditional, allowClientConfigUpdatesWhenUnlocked: true, ((BaseUnityPlugin)this).Logger); BindConfig(); Log = new BNLog(((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Config); if (flag) { LegacyConfigMigration.TryImport(((BaseUnityPlugin)this).Config, Log); } GameVersion val = default(GameVersion); ((GameVersion)(ref val))..ctor(1, 0, 21); if (Version.CurrentVersion < val || Version.CurrentVersion > val) { Log.Warning($"This build targets Valheim {val}, compiled against network version {41u}; running {Version.CurrentVersion}. Check PATCH FAILED messages and retest networking after game updates."); } else { Log.Message($"Valheim target version matched: {Version.CurrentVersion}, compiled against network version {41u}"); } _harmony = new Harmony("DIT.BetterNetworking10"); PatchInstaller.Install(_harmony); PortalGhostRefresh.Initialize(); RegisterRuntimeConfigHandlers(); if (_configSync.IsActive) { Log.Message("Conditional Config Sync active (optional integration, CCS >= 1.0.10)"); } else if (Chainloader.PluginInfos.ContainsKey("_shudnal.ConditionalConfigSync")) { Log.Warning("Conditional Config Sync is installed but optional synchronization is inactive; CCS 1.0.10 or newer is required"); } } private void Update() { PortalGhostRefresh.Tick(); } private void OnDestroy() { UnregisterRuntimeConfigHandlers(); CompressionState.Clear(); ConnectionBufferPatch.Clear(); PortalGhostRefresh.Clear(); SteamSendRatePatch.Clear(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void BindConfig() { //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Expected O, but got Unknown LockConfiguration = _configSync.BindLocking(((BaseUnityPlugin)this).Config, "00 - Compatibility", "Lock Configuration", defaultValue: true, "When Conditional Config Sync is installed, only server administrators may change server-controlled settings. Has no effect without CCS."); Mode = _configSync.Bind(((BaseUnityPlugin)this).Config, "00 - Compatibility", "Mode", CompatibilityMode.Balanced, "Balanced: the enabled feature switches below are applied. VanillaSafe: only compression is allowed; ZDO scheduling, queue, and Steam send-rate changes are disabled."); EnableCompression = _configSync.Bind(((BaseUnityPlugin)this).Config, "01 - Features", "Compression", defaultValue: true, "Compress traffic only when both peers run this compatible build."); EnableQueueSize = _configSync.Bind(((BaseUnityPlugin)this).Config, "01 - Features", "Queue Size", defaultValue: true, "Changes the ZDO send budget directly. Disabled in VanillaSafe mode."); EnableUpdateRate = _configSync.Bind(((BaseUnityPlugin)this).Config, "01 - Features", "Update Rate", defaultValue: true, "Allows a lower ZDO update frequency. Disabled in VanillaSafe mode."); EnableSendRate = _configSync.Bind(((BaseUnityPlugin)this).Config, "01 - Features", "Steam Send Rate", defaultValue: true, "Changes Steamworks send-rate limits. Has no effect with PlayFab/crossplay. Disabled in VanillaSafe mode."); EnableConnectionBuffer = _configSync.Bind(((BaseUnityPlugin)this).Config, "01 - Features", "New Connection ZDO Buffer", defaultValue: false, "Experimental and client-local because it runs before server config synchronization. Buffers early ZDOData packets per connection until ZDOMan registers the peer. OFF by default.", SyncMode.AlwaysClientControlled); EnablePortalGhostFix = _configSync.Bind(((BaseUnityPlugin)this).Config, "01 - Features", "Portal Ghost Fix", defaultValue: false, "Optional server-side portal observer refresh. Re-sends a teleported player's ZDO and related networked status-effect ZDOs; vanilla clients are supported. Disable the standalone Sfantul mod when using this.", SyncMode.AlwaysServerControlled); QueueSize = _configSync.Bind(((BaseUnityPlugin)this).Config, "02 - Networking", "Queue Size", QueueSizeOption.KB32, "ZDO send budget based on Valheim's reported queue size. Vanilla leaves the game's 10 KB budget unchanged."); UpdateRate = _configSync.Bind(((BaseUnityPlugin)this).Config, "02 - Networking", "Update Rate", UpdateRateOption.Percent100, "100 = vanilla 20 Hz timer; 75 = 15 Hz; 50 = 10 Hz."); MinimumSendRate = _configSync.Bind(((BaseUnityPlugin)this).Config, "03 - Steamworks", "Minimum Send Rate", SendRateOption.KB256, "Steamworks minimum send rate in KB/s. Keep this below the real upload capacity."); MaximumSendRate = _configSync.Bind(((BaseUnityPlugin)this).Config, "03 - Steamworks", "Maximum Send Rate", SendRateOption.KB1024, "Steamworks maximum send rate in KB/s."); ForceCrossplay = _configSync.Bind(((BaseUnityPlugin)this).Config, "04 - Dedicated Server", "Force Crossplay", ForceCrossplayOption.Vanilla, "Vanilla follows the server command line; PlayFab or Steamworks overrides the backend before server initialization. Requires restart and is disabled in VanillaSafe mode.", SyncMode.AlwaysServerControlled); PlayerLimit = _configSync.Bind(((BaseUnityPlugin)this).Config, "04 - Dedicated Server", "Player Limit", 10, new ConfigDescription("Dedicated server player limit. Requires restart.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 127), Array.Empty<object>()), SyncMode.AlwaysServerControlled); } private void RegisterRuntimeConfigHandlers() { EnableCompression.SettingChanged += OnCompressionSettingChanged; Mode.SettingChanged += OnNetworkRuntimeSettingChanged; EnableSendRate.SettingChanged += OnNetworkRuntimeSettingChanged; MinimumSendRate.SettingChanged += OnNetworkRuntimeSettingChanged; MaximumSendRate.SettingChanged += OnNetworkRuntimeSettingChanged; EnableConnectionBuffer.SettingChanged += OnNetworkRuntimeSettingChanged; } private void UnregisterRuntimeConfigHandlers() { if (EnableCompression != null) { EnableCompression.SettingChanged -= OnCompressionSettingChanged; } if (Mode != null) { Mode.SettingChanged -= OnNetworkRuntimeSettingChanged; } if (EnableSendRate != null) { EnableSendRate.SettingChanged -= OnNetworkRuntimeSettingChanged; } if (MinimumSendRate != null) { MinimumSendRate.SettingChanged -= OnNetworkRuntimeSettingChanged; } if (MaximumSendRate != null) { MaximumSendRate.SettingChanged -= OnNetworkRuntimeSettingChanged; } if (EnableConnectionBuffer != null) { EnableConnectionBuffer.SettingChanged -= OnNetworkRuntimeSettingChanged; } } private static void OnCompressionSettingChanged(object sender, EventArgs eventArgs) { CompressionPatch.RefreshNegotiation(); } private static void OnNetworkRuntimeSettingChanged(object sender, EventArgs eventArgs) { SteamSendRatePatch.Refresh(); if (!ConnectionBufferActive) { ConnectionBufferPatch.Clear(); } } internal static int RateBytesPerSecond(SendRateOption option) { return (int)option * 1024; } } public enum CompatibilityMode { Balanced, VanillaSafe } public enum QueueSizeOption { Vanilla = 10, KB32 = 32, KB48 = 48, KB64 = 64, KB80 = 80 } public enum UpdateRateOption { Percent100 = 100, Percent75 = 75, Percent50 = 50 } public enum SendRateOption { KB150 = 150, KB256 = 256, KB512 = 512, KB768 = 768, KB1024 = 1024 } public enum ForceCrossplayOption { Vanilla, PlayFab, Steamworks } internal static class PatchInstaller { private static int _applied; private static int _skipped; private static int _failed; internal static void Install(Harmony harmony) { BetterNetworking10.CompressionRuntimeAvailable = false; try { CompressionCodec.Initialize(); CompressionFrame.SelfTest(); BetterNetworking10.CompressionRuntimeAvailable = true; InstallCompression(harmony); } catch (Exception ex) { Skip("Compression", "self-test failed: " + ex.GetType().Name + ": " + ex.Message); BetterNetworking10.Log.Error("Compression was left disabled because its startup self-test failed"); } Patch(harmony, "ZDO queue budget (runtime guarded)", AccessTools.DeclaredMethod(typeof(ZDOMan), "SendZDOs", (Type[])null, (Type[])null), null, null, "Transpiler", typeof(QueueBudgetPatch)); Patch(harmony, "ZDO update rate (runtime guarded)", AccessTools.DeclaredMethod(typeof(ZDOMan), "SendZDOToPeers2", (Type[])null, (Type[])null), "Prefix", null, null, typeof(UpdateRatePatch)); Patch(harmony, "Steam send rate (runtime guarded)", AccessTools.DeclaredMethod(typeof(ZSteamSocket), "RegisterGlobalCallbacks", (Type[])null, (Type[])null), null, "Postfix", null, typeof(SteamSendRatePatch)); InstallConnectionBuffer(harmony); InstallDedicatedTweaks(harmony); BetterNetworking10.Log.Message($"Patch audit complete: {_applied} applied, {_skipped} skipped, {_failed} failed. Mode={BetterNetworking10.Mode.Value}"); } private static void InstallCompression(Harmony harmony) { Patch(harmony, "Compression connect", AccessTools.DeclaredMethod(typeof(ZNet), "OnNewConnection", (Type[])null, (Type[])null), null, "OnConnectPostfix", null, typeof(CompressionPatch)); Patch(harmony, "Compression disconnect pre", AccessTools.DeclaredMethod(typeof(ZNet), "Disconnect", (Type[])null, (Type[])null), "OnDisconnectPrefix", null, null, typeof(CompressionPatch)); Patch(harmony, "Compression disconnect post", AccessTools.DeclaredMethod(typeof(ZNet), "Disconnect", (Type[])null, (Type[])null), null, "OnDisconnectPostfix", null, typeof(CompressionPatch)); Patch(harmony, "Steam compress-once send", AccessTools.DeclaredMethod(typeof(ZSteamSocket), "Send", new Type[1] { typeof(ZPackage) }, (Type[])null), "SendPrefix", null, null, typeof(SteamCompressionPatch)); Patch(harmony, "Steam receive", AccessTools.DeclaredMethod(typeof(ZSteamSocket), "Recv", (Type[])null, (Type[])null), null, "ReceivePostfix", null, typeof(SteamCompressionPatch)); Patch(harmony, "PlayFab socket ctor()", AccessTools.DeclaredConstructor(typeof(ZPlayFabSocket), Type.EmptyTypes, false), null, "SocketOpenPostfix", null, typeof(PlayFabCompressionPatch)); Patch(harmony, "PlayFab socket ctor(string,callback)", AccessTools.DeclaredConstructor(typeof(ZPlayFabSocket), new Type[2] { typeof(string), typeof(Action<PlayFabMatchmakingServerData>) }, false), null, "SocketOpenPostfix", null, typeof(PlayFabCompressionPatch)); Patch(harmony, "PlayFab socket ctor(player)", AccessTools.DeclaredConstructor(typeof(ZPlayFabSocket), new Type[1] { typeof(PlayFabPlayer) }, false), null, "SocketOpenPostfix", null, typeof(PlayFabCompressionPatch)); Patch(harmony, "PlayFab socket dispose", AccessTools.DeclaredMethod(typeof(ZPlayFabSocket), "Dispose", (Type[])null, (Type[])null), null, "SocketClosePostfix", null, typeof(PlayFabCompressionPatch)); Patch(harmony, "PlayFab compress", AccessTools.DeclaredMethod(typeof(PlayFabZLibWorkQueue), "DoCompress", (Type[])null, (Type[])null), "CompressPrefix", null, null, typeof(PlayFabCompressionPatch)); Patch(harmony, "PlayFab decompress", AccessTools.DeclaredMethod(typeof(PlayFabZLibWorkQueue), "DoUncompress", (Type[])null, (Type[])null), "DecompressPrefix", null, null, typeof(PlayFabCompressionPatch)); Patch(harmony, "PlayFab direct compress", AccessTools.DeclaredMethod(typeof(PlayFabZLibWorkQueue), "CompressOnThisThread", (Type[])null, (Type[])null), "DirectCompressPrefix", null, null, typeof(PlayFabCompressionPatch)); Patch(harmony, "PlayFab direct decompress", AccessTools.DeclaredMethod(typeof(PlayFabZLibWorkQueue), "UncompressOnThisThread", (Type[])null, (Type[])null), "DirectDecompressPrefix", null, null, typeof(PlayFabCompressionPatch)); } private static void InstallConnectionBuffer(Harmony harmony) { Patch(harmony, "Connection buffer start", AccessTools.DeclaredMethod(typeof(ZNet), "OnNewConnection", (Type[])null, (Type[])null), null, "OnNewConnectionPostfix", null, typeof(ConnectionBufferPatch)); Patch(harmony, "Connection buffer replay", AccessTools.DeclaredMethod(typeof(ZDOMan), "AddPeer", (Type[])null, (Type[])null), null, "AddPeerPostfix", null, typeof(ConnectionBufferPatch)); Patch(harmony, "Connection buffer clear", AccessTools.DeclaredMethod(typeof(ZNet), "Shutdown", (Type[])null, (Type[])null), null, "ShutdownPostfix", null, typeof(ConnectionBufferPatch)); } private static void InstallDedicatedTweaks(Harmony harmony) { Patch(harmony, "Dedicated backend selection (runtime guarded)", AccessTools.DeclaredMethod(typeof(ZNet), "SetServer", new Type[6] { typeof(bool), typeof(bool), typeof(bool), typeof(string), typeof(string), typeof(World) }, (Type[])null), "SetServerPrefix", null, null, typeof(DedicatedPatch)); Patch(harmony, "Dedicated player limit (runtime value)", AccessTools.DeclaredMethod(typeof(ZNet), "RPC_PeerInfo", (Type[])null, (Type[])null), null, null, "PlayerLimitTranspiler", typeof(DedicatedPatch)); } private static void Patch(Harmony harmony, string label, MethodBase target, string prefix = null, string postfix = null, string transpiler = null, Type patchType = null) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (target == null) { _failed++; BetterNetworking10.Log.Error("PATCH FAILED " + label + ": target method not found; feature left vanilla"); return; } try { HarmonyMethod val = ((prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.DeclaredMethod(patchType, prefix, (Type[])null, (Type[])null))); HarmonyMethod val2 = ((postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.DeclaredMethod(patchType, postfix, (Type[])null, (Type[])null))); HarmonyMethod val3 = ((transpiler == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.DeclaredMethod(patchType, transpiler, (Type[])null, (Type[])null))); if ((prefix != null && val.method == null) || (postfix != null && val2.method == null) || (transpiler != null && val3.method == null)) { throw new MissingMethodException("patch method not found"); } harmony.Patch(target, val, val2, val3, (HarmonyMethod)null, (HarmonyMethod)null); _applied++; BetterNetworking10.Log.Message("PATCH OK " + label + ": " + target.DeclaringType?.Name + "." + target.Name); } catch (Exception ex) { _failed++; BetterNetworking10.Log.Error("PATCH FAILED " + label + ": " + ex.GetType().Name + ": " + ex.Message + "; feature left vanilla"); } } private static void Skip(string label, string reason) { _skipped++; BetterNetworking10.Log.Message("PATCH SKIP " + label + ": " + reason); } } internal sealed class BNLog { internal enum LogLevel { Warning, Message, Info } private readonly ManualLogSource _logger; private readonly ConfigEntry<LogLevel> _level; internal bool IsInfo => _level.Value >= LogLevel.Info; internal BNLog(ManualLogSource logger, ConfigFile config) { _logger = logger; _level = config.Bind<LogLevel>("99 - Logging", "Log Level", LogLevel.Message, "Warning, Message, or Info (verbose packet compression logging). "); } internal void Error(object value) { _logger.LogError(value); } internal void Warning(object value) { _logger.LogWarning(value); } internal void Message(object value) { if (_level.Value >= LogLevel.Message) { _logger.LogMessage(value); } } internal void Info(object value) { if (_level.Value >= LogLevel.Info) { _logger.LogInfo(value); } } } internal static class CompressionCodec { private const string DictionaryResource = "DIT.BetterNetworking10.dict.small"; private static Compressor _compressor; private static Decompressor _decompressor; private static readonly object Sync = new object(); internal static void Initialize() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DIT.BetterNetworking10.dict.small"); if (stream == null) { throw new InvalidOperationException("Embedded Zstd dictionary is missing"); } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num == 0) { throw new EndOfStreamException("Could not read embedded Zstd dictionary"); } } _compressor = new Compressor(1); _compressor.LoadDictionary(array); _decompressor = new Decompressor(); _decompressor.LoadDictionary(array); } internal static byte[] Compress(byte[] input) { lock (Sync) { return _compressor.Wrap((ReadOnlySpan<byte>)input).ToArray(); } } internal static byte[] Decompress(byte[] input) { lock (Sync) { return _decompressor.Unwrap((ReadOnlySpan<byte>)input, int.MaxValue).ToArray(); } } } internal static class CompressionFrame { private static readonly byte[] Magic = new byte[4] { 66, 78, 49, 48 }; private const int HeaderSize = 5; private const byte RawPayload = 0; private const byte CompressedPayload = 1; internal static byte[] Encode(byte[] input) { return Encode(input, diagnostics: true); } private static byte[] Encode(byte[] input, bool diagnostics) { if (HasHeader(input)) { if (diagnostics) { BetterNetworking10.Log.Warning("Prevented duplicate Better Networking compression frame"); } return input; } byte[] array = CompressionCodec.Compress(input); bool flag = array.Length < input.Length; byte[] array2 = (flag ? array : input); byte[] array3 = new byte[5 + array2.Length]; Buffer.BlockCopy(Magic, 0, array3, 0, Magic.Length); array3[Magic.Length] = (byte)(flag ? 1 : 0); Buffer.BlockCopy(array2, 0, array3, 5, array2.Length); if (diagnostics && BetterNetworking10.Log.IsInfo && input.Length > 256) { if (flag) { BetterNetworking10.Log.Info($"Compression sent {input.Length} B -> {array3.Length} B ({100f * (float)array3.Length / (float)input.Length:0}%, framed)"); } else { BetterNetworking10.Log.Info($"Compression bypassed for {input.Length} B packet because it would grow ({array3.Length} B framed)"); } } return array3; } internal static bool TryDecode(byte[] input, out byte[] output) { output = null; if (!HasHeader(input)) { return false; } int num = input.Length - 5; byte[] array = new byte[num]; Buffer.BlockCopy(input, 5, array, 0, num); byte b = input[Magic.Length]; switch (b) { case 0: output = array; break; case 1: output = CompressionCodec.Decompress(array); break; default: throw new InvalidDataException($"Unknown Better Networking frame type {b}"); } if (BetterNetworking10.Log.IsInfo && output.Length > 256) { BetterNetworking10.Log.Info($"Compression received {input.Length} B -> {output.Length} B (framed)"); } return true; } internal static bool HasHeader(byte[] input) { if (input == null || input.Length < 5) { return false; } for (int i = 0; i < Magic.Length; i++) { if (input[i] != Magic[i]) { return false; } } return true; } internal static void SelfTest() { byte[] array = Enumerable.Repeat((byte)90, 1024).ToArray(); byte[] array2 = Encode(array); if (!TryDecode(array2, out var output) || !((ReadOnlySpan<byte>)array).SequenceEqual((ReadOnlySpan<byte>)output)) { throw new InvalidDataException("Compression frame round-trip failed"); } if (array2 != Encode(array2, diagnostics: false)) { throw new InvalidDataException("Compression frame duplicate guard failed"); } } } internal static class CompressionState { internal sealed class PeerState { internal int Version; internal bool Enabled; internal volatile bool Sending; internal volatile bool Receiving; internal volatile bool WarnedUnframed; } internal const int ProtocolVersion = 8; private static readonly ConcurrentDictionary<ISocket, PeerState> Peers = new ConcurrentDictionary<ISocket, PeerState>(); internal static void Add(ISocket socket) { if (socket != null) { Peers[socket] = new PeerState(); } } internal static void Remove(ISocket socket) { if (socket != null) { Peers.TryRemove(socket, out var _); } } internal static bool TryGet(ISocket socket, out PeerState state) { state = null; return socket != null && Peers.TryGetValue(socket, out state); } internal static void Clear() { Peers.Clear(); } } internal static class PeerLookup { internal static ZNetPeer ByRpc(ZRpc rpc) { if (rpc == null || (Object)(object)ZNet.instance == (Object)null) { return null; } return ((IEnumerable<ZNetPeer>)ZNet.instance.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer peer) => peer.m_rpc == rpc)); } internal static string Name(ZNetPeer peer) { if (peer == null) { return "[unknown]"; } if (peer.m_server) { return "[server]"; } string text = ((peer.m_socket == null) ? "?" : peer.m_socket.GetHostName()); return peer.m_playerName + "[" + text + "]"; } } internal static class CompressionPatch { private const string RpcVersion = "CW_Jesse.BetterNetworking.CompressionVersion"; private const string RpcEnabled = "CW_Jesse.BetterNetworking.CompressionEnabled"; private const string RpcStarted = "CW_Jesse.BetterNetworking.CompressedStarted"; internal static void OnConnectPostfix(ZNetPeer peer) { if (peer?.m_socket != null && peer.m_rpc != null) { CompressionState.Add(peer.m_socket); peer.m_rpc.Register<int>("CW_Jesse.BetterNetworking.CompressionVersion", (Action<ZRpc, int>)ReceiveVersion); peer.m_rpc.Register<bool>("CW_Jesse.BetterNetworking.CompressionEnabled", (Action<ZRpc, bool>)ReceiveEnabled); peer.m_rpc.Register<bool>("CW_Jesse.BetterNetworking.CompressedStarted", (Action<ZRpc, bool>)ReceiveStarted); peer.m_rpc.Invoke("CW_Jesse.BetterNetworking.CompressionVersion", new object[1] { 8 }); BetterNetworking10.Log.Message("Compression peer connected: " + PeerLookup.Name(peer)); } } internal static void OnDisconnectPrefix(ZNetPeer peer) { BetterNetworking10.Log.Message("Compression peer disconnected: " + PeerLookup.Name(peer)); } internal static void OnDisconnectPostfix(ZNetPeer peer) { CompressionState.Remove(peer?.m_socket); } internal static void RefreshNegotiation() { if ((Object)(object)ZNet.instance == (Object)null) { return; } ZNetPeer[] array = ZNet.instance.GetPeers().ToArray(); foreach (ZNetPeer val in array) { if (val?.m_rpc != null && val.m_socket != null && CompressionState.TryGet(val.m_socket, out var _)) { try { SendEnabled(val); } catch (Exception ex) { BetterNetworking10.Log.Warning("Could not refresh compression state for " + PeerLookup.Name(val) + ": " + ex.Message); } } } } private static void ReceiveVersion(ZRpc rpc, int version) { ZNetPeer val = PeerLookup.ByRpc(rpc); if (val != null && CompressionState.TryGet(val.m_socket, out var state)) { state.Version = version; if (version == 8) { BetterNetworking10.Log.Message($"Compression compatible with {PeerLookup.Name(val)} (protocol {version})"); SendEnabled(val); } else if (version > 0) { BetterNetworking10.Log.Warning($"Compression disabled with {PeerLookup.Name(val)}: protocol {version}, expected {8}"); } } } private static void ReceiveEnabled(ZRpc rpc, bool enabled) { ZNetPeer val = PeerLookup.ByRpc(rpc); if (val != null && CompressionState.TryGet(val.m_socket, out var state)) { state.Enabled = enabled; SendStarted(val, BetterNetworking10.CompressionActive && enabled && state.Version == 8); } } private static void ReceiveStarted(ZRpc rpc, bool started) { ZNetPeer val = PeerLookup.ByRpc(rpc); if (val != null && CompressionState.TryGet(val.m_socket, out var state)) { state.Receiving = started; state.WarnedUnframed = false; BetterNetworking10.Log.Message($"Compression from {PeerLookup.Name(val)}: {started}"); } } private static void SendEnabled(ZNetPeer peer) { peer.m_rpc.Invoke("CW_Jesse.BetterNetworking.CompressionEnabled", new object[1] { BetterNetworking10.CompressionActive }); if (CompressionState.TryGet(peer.m_socket, out var state)) { SendStarted(peer, BetterNetworking10.CompressionActive && state.Enabled && state.Version == 8); } } private static void SendStarted(ZNetPeer peer, bool started) { if (CompressionState.TryGet(peer.m_socket, out var state) && state.Sending != started) { peer.m_rpc.Invoke("CW_Jesse.BetterNetworking.CompressedStarted", new object[1] { started }); Flush(peer.m_socket); state.Sending = started; BetterNetworking10.Log.Message($"Compression to {PeerLookup.Name(peer)}: {started}"); } } private static void Flush(ISocket socket) { if (socket is ZSteamSocket) { socket.Flush(); return; } ZPlayFabSocket val = (ZPlayFabSocket)(object)((socket is ZPlayFabSocket) ? socket : null); if (val != null) { PlayFabCompressionPatch.Flush(val); } } } internal static class SteamCompressionPatch { internal static void SendPrefix(ZSteamSocket __instance, ref ZPackage pkg) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown if (pkg != null && CompressionState.TryGet((ISocket)(object)__instance, out var state) && state.Sending) { pkg = new ZPackage(CompressionFrame.Encode(pkg.GetArray())); } } internal static void ReceivePostfix(ZSteamSocket __instance, ref ZPackage __result) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown if (__result == null || !CompressionState.TryGet((ISocket)(object)__instance, out var state)) { return; } byte[] array = __result.GetArray(); try { if (CompressionFrame.TryDecode(array, out var output)) { __result = new ZPackage(output); state.WarnedUnframed = false; if (!state.Receiving) { state.Receiving = true; BetterNetworking10.Log.Warning("Received framed Steamworks packet before compression-start state; recovered automatically"); } } else if (state.Receiving && !state.WarnedUnframed) { state.WarnedUnframed = true; BetterNetworking10.Log.Warning("Received an unframed Steamworks packet while compression was active; packet preserved"); } } catch (Exception ex) { BetterNetworking10.Log.Error("Invalid Better Networking Steamworks frame dropped: " + ex.Message); __result = null; } } } internal static class PlayFabCompressionPatch { private static readonly ConcurrentDictionary<PlayFabZLibWorkQueue, ZPlayFabSocket> Sockets = new ConcurrentDictionary<PlayFabZLibWorkQueue, ZPlayFabSocket>(); private static readonly FieldInfo WorkQueueField = AccessTools.Field(typeof(ZPlayFabSocket), "m_zlibWorkQueue"); private static readonly FieldInfo WorkLockField = AccessTools.Field(typeof(PlayFabZLibWorkQueue), "m_lock"); private static readonly FieldInfo WorkersField = AccessTools.Field(typeof(PlayFabZLibWorkQueue), "s_workers"); private static readonly MethodInfo ExecuteMethod = AccessTools.Method(typeof(PlayFabZLibWorkQueue), "Execute", (Type[])null, (Type[])null); private static readonly MethodInfo LateUpdateMethod = AccessTools.Method(typeof(ZPlayFabSocket), "LateUpdate", (Type[])null, (Type[])null); internal static void SocketOpenPostfix(ZPlayFabSocket __instance, PlayFabZLibWorkQueue ___m_zlibWorkQueue) { if (__instance != null && ___m_zlibWorkQueue != null) { Sockets[___m_zlibWorkQueue] = __instance; } } internal static void SocketClosePostfix(PlayFabZLibWorkQueue ___m_zlibWorkQueue) { if (___m_zlibWorkQueue != null) { Sockets.TryRemove(___m_zlibWorkQueue, out var _); } } internal static bool CompressPrefix(PlayFabZLibWorkQueue __instance, Queue<byte[]> ___m_inCompress, Queue<byte[]> ___m_outCompress) { if (!Sockets.TryGetValue(__instance, out var value)) { return true; } if (!CompressionState.TryGet((ISocket)(object)value, out var state) || !state.Sending) { return true; } while (___m_inCompress.Count > 0) { byte[] input = ___m_inCompress.Dequeue(); try { ___m_outCompress.Enqueue(CompressionFrame.Encode(input)); } catch (Exception ex) { BetterNetworking10.Log.Error("PlayFab compression failed: " + ex.Message); } } return false; } internal static bool DecompressPrefix(PlayFabZLibWorkQueue __instance, Queue<byte[]> ___m_inDecompress, Queue<byte[]> ___m_outDecompress) { if (!Sockets.TryGetValue(__instance, out var value)) { return true; } CompressionState.TryGet((ISocket)(object)value, out var state); while (___m_inDecompress.Count > 0) { byte[] array = ___m_inDecompress.Dequeue(); bool flag = CompressionFrame.HasHeader(array); try { if (CompressionFrame.TryDecode(array, out var output)) { ___m_outDecompress.Enqueue(output); if (state != null && !state.Receiving) { state.Receiving = true; BetterNetworking10.Log.Warning("Received framed PlayFab packet before compression-start state; recovered automatically"); } continue; } } catch (Exception ex) { BetterNetworking10.Log.Error("Invalid Better Networking PlayFab frame dropped: " + ex.Message); continue; } if (!flag) { try { byte[] item = ZlibStream.UncompressBuffer(array); ___m_outDecompress.Enqueue(item); } catch { BetterNetworking10.Log.Warning("PlayFab packet was neither BN-framed nor vanilla-zlib; preserving raw data"); ___m_outDecompress.Enqueue(array); } } } return false; } internal static bool DirectCompressPrefix(PlayFabZLibWorkQueue __instance, byte[] payload, ref byte[] __result) { if (!Sockets.TryGetValue(__instance, out var value)) { return true; } if (!CompressionState.TryGet((ISocket)(object)value, out var state) || !state.Sending) { return true; } __result = CompressionFrame.Encode(payload); return false; } internal static bool DirectDecompressPrefix(PlayFabZLibWorkQueue __instance, byte[] payload, ref byte[] __result) { if (!Sockets.TryGetValue(__instance, out var value)) { return true; } if (!CompressionFrame.HasHeader(payload)) { return true; } try { if (!CompressionFrame.TryDecode(payload, out __result)) { return true; } if (CompressionState.TryGet((ISocket)(object)value, out var state) && !state.Receiving) { state.Receiving = true; BetterNetworking10.Log.Warning("Recovered an early/direct BN-compressed PlayFab packet"); } return false; } catch { return true; } } internal static void Flush(ZPlayFabSocket socket) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (socket == null || WorkQueueField == null || WorkLockField == null || WorkersField == null || ExecuteMethod == null || LateUpdateMethod == null) { return; } _ = (PlayFabZLibWorkQueue)WorkQueueField.GetValue(socket); object value = WorkLockField.GetValue(null); List<PlayFabZLibWorkQueue> list = (List<PlayFabZLibWorkQueue>)WorkersField.GetValue(null); lock (value) { PlayFabZLibWorkQueue[] array = list.ToArray(); foreach (PlayFabZLibWorkQueue obj in array) { ExecuteMethod.Invoke(obj, Array.Empty<object>()); } } LateUpdateMethod.Invoke(socket, null); } } internal static class ConnectionBufferPatch { private const int MaximumPacketsPerConnection = 256; private static readonly ConcurrentDictionary<ZRpc, List<ZPackage>> Buffers = new ConcurrentDictionary<ZRpc, List<ZPackage>>(); private static readonly MethodInfo ReceiveZdoData = AccessTools.DeclaredMethod(typeof(ZDOMan), "RPC_ZDOData", (Type[])null, (Type[])null); internal static void OnNewConnectionPostfix(ZNet __instance, ZNetPeer peer) { if (!BetterNetworking10.ConnectionBufferActive || (Object)(object)__instance == (Object)null || peer?.m_rpc == null || __instance.IsServer()) { return; } List<ZPackage> buffer = Buffers.GetOrAdd(peer.m_rpc, (ZRpc _) => new List<ZPackage>()); peer.m_rpc.Register<ZPackage>("ZDOData", (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage package) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown lock (buffer) { if (buffer.Count >= 256) { BetterNetworking10.Log.Error("Connection ZDO buffer reached 256 packets; dropping additional early packets"); } else { buffer.Add(new ZPackage(package.GetArray())); } } }); } internal static void AddPeerPostfix(ZDOMan __instance, ZNetPeer netPeer) { if (__instance == null || netPeer?.m_rpc == null || ReceiveZdoData == null || !Buffers.TryRemove(netPeer.m_rpc, out var value) || !BetterNetworking10.ConnectionBufferActive) { return; } lock (value) { BetterNetworking10.Log.Warning($"Replaying {value.Count} early ZDOData packet(s) for one connection"); foreach (ZPackage item in value) { ReceiveZdoData.Invoke(__instance, new object[2] { netPeer.m_rpc, item }); } } } internal static void ShutdownPostfix() { Clear(); } internal static void Clear() { Buffers.Clear(); } } internal static class DedicatedPatch { internal static void SetServerPrefix() { //IL_0030: 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) if (BetterNetworking10.IsDedicated && !BetterNetworking10.SafeMode) { switch (BetterNetworking10.ForceCrossplay.Value) { case ForceCrossplayOption.PlayFab: ZNet.m_onlineBackend = (OnlineBackendType)1; break; case ForceCrossplayOption.Steamworks: ZNet.m_onlineBackend = (OnlineBackendType)0; break; } } } internal static int GetPlayerLimit() { return BetterNetworking10.SafeMode ? 10 : BetterNetworking10.PlayerLimit.Value; } internal static IEnumerable<CodeInstruction> PlayerLimitTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "GetNrOfPlayers", (Type[])null, (Type[])null); MethodInfo operand = AccessTools.DeclaredMethod(typeof(DedicatedPatch), "GetPlayerLimit", (Type[])null, (Type[])null); int num = -1; for (int i = 1; i < list.Count; i++) { if ((CodeInstructionExtensions.Is(list[i], OpCodes.Ldc_I4_S, (object)(sbyte)10) || CodeInstructionExtensions.Is(list[i], OpCodes.Ldc_I4, (object)10)) && CodeInstructionExtensions.Calls(list[i - 1], methodInfo)) { if (num != -1) { BetterNetworking10.Log.Error("Player-limit transpiler found multiple guard constants; leaving RPC_PeerInfo unmodified"); return list; } num = i; } } if (num == -1) { BetterNetworking10.Log.Error("Player-limit transpiler could not identify the 1.0 server-full guard; leaving RPC_PeerInfo unmodified"); return list; } list[num].opcode = OpCodes.Call; list[num].operand = operand; BetterNetworking10.Log.Message($"Player-limit transpiler verified 1/1 IL match; limit={BetterNetworking10.PlayerLimit.Value}"); return list; } } internal static class LegacyConfigMigration { private const string LegacyFileName = "CW_Jesse.BetterNetworking.cfg"; internal static void TryImport(ConfigFile config, BNLog log) { string path = Path.Combine(Paths.ConfigPath, "CW_Jesse.BetterNetworking.cfg"); if (!File.Exists(path)) { return; } try { Dictionary<string, string> values = ReadValues(path); int num = 0; if (TryGet(values, "Networking", "Compression Enabled", out var value) && TryParseBoolean(value, out var result)) { BetterNetworking10.EnableCompression.Value = result; num++; } if (TryGet(values, "Networking", "Queue Size", out var value2) && TryParseQueueSize(value2, out var result2)) { BetterNetworking10.EnableQueueSize.Value = true; BetterNetworking10.QueueSize.Value = result2; num++; } if (TryGet(values, "Networking", "Update Rate", out var value3) && TryParseUpdateRate(value3, out var result3)) { BetterNetworking10.EnableUpdateRate.Value = true; BetterNetworking10.UpdateRate.Value = result3; num++; } if (TryGet(values, "Networking (Steamworks)", "Minimum Send Rate", out var value4) && TryParseSendRate(value4, out var result4)) { BetterNetworking10.EnableSendRate.Value = true; BetterNetworking10.MinimumSendRate.Value = result4; num++; } if (TryGet(values, "Networking (Steamworks)", "Maximum Send Rate", out var value5) && TryParseSendRate(value5, out var result5)) { BetterNetworking10.EnableSendRate.Value = true; BetterNetworking10.MaximumSendRate.Value = result5; num++; } if (TryGet(values, "Dedicated Server", "Force Crossplay", out var value6) && TryParseCrossplay(value6, out var result6)) { BetterNetworking10.ForceCrossplay.Value = result6; num++; } if (TryGet(values, "Dedicated Server", "Player Limit", out var value7) && int.TryParse(value7.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result7)) { BetterNetworking10.PlayerLimit.Value = Math.Max(1, Math.Min(127, result7)); num++; } if (TryGet(values, "Logging", "Log Level", out var value8) && TryParseLogLevel(value8, out var result8)) { config.Bind<BNLog.LogLevel>("99 - Logging", "Log Level", BNLog.LogLevel.Message, (ConfigDescription)null).Value = result8; num++; } BetterNetworking10.EnableConnectionBuffer.Value = false; config.Save(); log.Message(string.Format("Imported {0} setting(s) from legacy config {1}. The old file was left unchanged.", num, "CW_Jesse.BetterNetworking.cfg")); } catch (Exception ex) { log.Warning("Legacy config import skipped: " + ex.GetType().Name + ": " + ex.Message); } } private static Dictionary<string, string> ReadValues(string path) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); string section = string.Empty; string[] array = File.ReadAllLines(path); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length == 0 || text2.StartsWith("#") || text2.StartsWith(";")) { continue; } if (text2.StartsWith("[") && text2.EndsWith("]")) { section = text2.Substring(1, text2.Length - 2).Trim(); continue; } int num = text2.IndexOf('='); if (num > 0) { string key = text2.Substring(0, num).Trim(); string value = text2.Substring(num + 1).Trim(); dictionary[MakeKey(section, key)] = value; } } return dictionary; } private static bool TryGet(Dictionary<string, string> values, string section, string key, out string value) { return values.TryGetValue(MakeKey(section, key), out value); } private static string MakeKey(string section, string key) { return section + "\n" + key; } private static string Normalize(string value) { return new string(value.Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray()); } private static bool TryParseBoolean(string value, out bool result) { string text = Normalize(value); if (text == "true" || text == "enabled") { result = true; return true; } if (text == "false" || text == "disabled") { result = false; return true; } result = false; return false; } private static bool TryParseQueueSize(string value, out QueueSizeOption result) { string text = Normalize(value); if (text.Contains("80")) { result = QueueSizeOption.KB80; } else if (text.Contains("64")) { result = QueueSizeOption.KB64; } else if (text.Contains("48")) { result = QueueSizeOption.KB48; } else if (text.Contains("32")) { result = QueueSizeOption.KB32; } else { if (!text.Contains("vanilla") && !text.Contains("10")) { result = (QueueSizeOption)0; return false; } result = QueueSizeOption.Vanilla; } return true; } private static bool TryParseUpdateRate(string value, out UpdateRateOption result) { string text = Normalize(value); if (text.Contains("100")) { result = UpdateRateOption.Percent100; } else if (text.Contains("75")) { result = UpdateRateOption.Percent75; } else { if (!text.Contains("50")) { result = (UpdateRateOption)0; return false; } result = UpdateRateOption.Percent50; } return true; } private static bool TryParseSendRate(string value, out SendRateOption result) { string text = Normalize(value); if (text.Contains("1024")) { result = SendRateOption.KB1024; } else if (text.Contains("768")) { result = SendRateOption.KB768; } else if (text.Contains("512")) { result = SendRateOption.KB512; } else if (text.Contains("256")) { result = SendRateOption.KB256; } else { if (!text.Contains("150")) { result = (SendRateOption)0; return false; } result = SendRateOption.KB150; } return true; } private static bool TryParseCrossplay(string value, out ForceCrossplayOption result) { string text = Normalize(value); if (text.Contains("playfab") || text.Contains("enabled")) { result = ForceCrossplayOption.PlayFab; } else if (text.Contains("steamworks") || text.Contains("disabled")) { result = ForceCrossplayOption.Steamworks; } else { if (!text.Contains("vanilla")) { result = ForceCrossplayOption.Vanilla; return false; } result = ForceCrossplayOption.Vanilla; } return true; } private static bool TryParseLogLevel(string value, out BNLog.LogLevel result) { string text = Normalize(value); if (text.Contains("info")) { result = BNLog.LogLevel.Info; } else if (text.Contains("message")) { result = BNLog.LogLevel.Message; } else { if (!text.Contains("warning")) { result = BNLog.LogLevel.Warning; return false; } result = BNLog.LogLevel.Warning; } return true; } } internal static class QueueBudgetPatch { internal static int GetBudget() { return BetterNetworking10.QueueActive ? BetterNetworking10.QueueBudgetBytes : 10240; } internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); int num = list.Count((CodeInstruction i) => CodeInstructionExtensions.Is(i, OpCodes.Ldc_I4, (object)10240)); if (num != 2) { BetterNetworking10.Log.Error($"Queue transpiler expected exactly 2 vanilla 10240 constants but found {num}; leaving SendZDOs unmodified"); return list; } MethodInfo operand = AccessTools.DeclaredMethod(typeof(QueueBudgetPatch), "GetBudget", (Type[])null, (Type[])null); foreach (CodeInstruction item in list) { if (CodeInstructionExtensions.Is(item, OpCodes.Ldc_I4, (object)10240)) { item.opcode = OpCodes.Call; item.operand = operand; } } BetterNetworking10.Log.Message($"Queue transpiler verified 2/2 IL matches; budget={BetterNetworking10.QueueBudgetBytes / 1024} KB"); return list; } } internal static class UpdateRatePatch { internal static void Prefix(ref float dt) { if (BetterNetworking10.UpdateRateActive) { dt *= BetterNetworking10.UpdateRateMultiplier; } } } internal static class SteamSendRatePatch { private static bool _callbacksRegistered; private static bool _originalValuesCaptured; private static bool _customValuesApplied; private static int _originalMinimum; private static int _originalMaximum; internal static void Postfix() { _callbacksRegistered = true; CaptureOriginalValues(); ApplyCurrent(); } internal static void Refresh() { if (_callbacksRegistered) { ApplyCurrent(); } } internal static void Clear() { if (_callbacksRegistered && _customValuesApplied && _originalValuesCaptured) { Set((ESteamNetworkingConfigValue)10, _originalMinimum, "restored"); Set((ESteamNetworkingConfigValue)11, _originalMaximum, "restored"); } _callbacksRegistered = false; _originalValuesCaptured = false; _customValuesApplied = false; _originalMinimum = 0; _originalMaximum = 0; } private static void ApplyCurrent() { if (!BetterNetworking10.SendRateActive) { if (_customValuesApplied && _originalValuesCaptured) { Set((ESteamNetworkingConfigValue)10, _originalMinimum, "restored"); Set((ESteamNetworkingConfigValue)11, _originalMaximum, "restored"); } _customValuesApplied = false; return; } int num = BetterNetworking10.RateBytesPerSecond(BetterNetworking10.MinimumSendRate.Value); int num2 = BetterNetworking10.RateBytesPerSecond(BetterNetworking10.MaximumSendRate.Value); if (num > num2) { int num3 = num; num = num2; num2 = num3; BetterNetworking10.Log.Warning("Steam send-rate minimum exceeded maximum; values were swapped at runtime"); } Set((ESteamNetworkingConfigValue)10, num, "configured"); Set((ESteamNetworkingConfigValue)11, num2, "configured"); _customValuesApplied = true; } private static void CaptureOriginalValues() { if (!_originalValuesCaptured) { if (!TryGet((ESteamNetworkingConfigValue)10, out _originalMinimum) || !TryGet((ESteamNetworkingConfigValue)11, out _originalMaximum)) { BetterNetworking10.Log.Warning("Could not capture the original Steamworks send-rate limits; live disabling will leave the latest configured values in place until restart"); } else { _originalValuesCaptured = true; } } } private static bool TryGet(ESteamNetworkingConfigValue key, out int value) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_001e: 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_004e: 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_0053: Invalid comparison between Unknown and I4 //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Invalid comparison between Unknown and I4 //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 value = 0; ulong num = 4uL; byte[] value2 = new byte[4]; GCHandle gCHandle = GCHandle.Alloc(value2, GCHandleType.Pinned); try { ESteamNetworkingConfigDataType val2 = default(ESteamNetworkingConfigDataType); ESteamNetworkingGetConfigValueResult val = (BetterNetworking10.IsDedicated ? SteamGameServerNetworkingUtils.GetConfigValue(key, (ESteamNetworkingConfigScope)1, IntPtr.Zero, ref val2, gCHandle.AddrOfPinnedObject(), ref num) : SteamNetworkingUtils.GetConfigValue(key, (ESteamNetworkingConfigScope)1, IntPtr.Zero, ref val2, gCHandle.AddrOfPinnedObject(), ref num)); if (((int)val != 1 && (int)val != 2) || (int)val2 != 1 || num < 4) { return false; } value = BitConverter.ToInt32(value2, 0); return true; } catch (Exception ex) { BetterNetworking10.Log.Warning($"Could not read Steamworks {key}: {ex.Message}"); return false; } finally { gCHandle.Free(); } } private static void Set(ESteamNetworkingConfigValue key, int value, string action) { //IL_007b: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) GCHandle gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned); try { if (BetterNetworking10.IsDedicated) { SteamGameServerNetworkingUtils.SetConfigValue(key, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle.AddrOfPinnedObject()); } else { SteamNetworkingUtils.SetConfigValue(key, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle.AddrOfPinnedObject()); } BetterNetworking10.Log.Message($"Steamworks {key} {action}: {value / 1024} KB/s"); } catch (Exception ex) { BetterNetworking10.Log.Error($"Could not set Steamworks {key}: {ex.Message}"); } finally { gCHandle.Free(); } } } internal static class PortalGhostRefresh { private const string StandalonePluginGuid = "sfantul.portalobserverfix"; private const float CheckIntervalSeconds = 0.25f; private const float DelayedRefreshSeconds = 0.75f; private const float MinimumJumpDistance = 64f; private const float MinimumJumpDistanceSquared = 4096f; private static readonly Dictionary<ZDOID, Vector3> LastPositions = new Dictionary<ZDOID, Vector3>(); private static readonly Dictionary<ZDOID, float> DelayedRefreshes = new Dictionary<ZDOID, float>(); private static readonly HashSet<ZDOID> ActivePlayers = new HashSet<ZDOID>(); private static readonly List<ZDOID> TemporaryIds = new List<ZDOID>(); private static ZDOMan _manager; private static float _nextCheck; private static bool _externalModInstalled; private static bool _runtimeDisabled; internal static void Initialize() { _externalModInstalled = Chainloader.PluginInfos.ContainsKey("sfantul.portalobserverfix"); _runtimeDisabled = false; if (!BetterNetworking10.PortalGhostFixActive) { BetterNetworking10.Log.Message("FEATURE SKIP Portal ghost fix: disabled by configuration"); } else if (_externalModInstalled) { BetterNetworking10.Log.Warning("FEATURE SKIP Portal ghost fix: standalone Sfantul-PortalGhostFix detected; built-in refresh disabled to avoid duplicate sends"); } else { BetterNetworking10.Log.Message("FEATURE ON Portal ghost fix: server-side player and linked status-effect refresh; vanilla clients supported"); } } internal static void Tick() { //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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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_0186: 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_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) if (!BetterNetworking10.PortalGhostFixActive || _externalModInstalled || _runtimeDisabled) { return; } ZNet instance = ZNet.instance; ZDOMan instance2 = ZDOMan.instance; if ((Object)(object)instance == (Object)null || !instance.IsServer() || instance2 == null) { if (_manager != null) { ClearRuntimeState(); } return; } if (_manager != instance2) { ClearRuntimeState(); _manager = instance2; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _nextCheck) { return; } _nextCheck = realtimeSinceStartup + 0.25f; try { ActivePlayers.Clear(); foreach (PlayerInfo player in instance.GetPlayerList()) { ZDOID characterID = player.m_characterID; if (characterID == ZDOID.None) { continue; } ActivePlayers.Add(characterID); ZDO zDO = instance2.GetZDO(characterID); if (zDO == null) { LastPositions.Remove(characterID); DelayedRefreshes.Remove(characterID); continue; } Vector3 position = zDO.GetPosition(); if (LastPositions.TryGetValue(characterID, out var value)) { Vector3 val = position - value; if (((Vector3)(ref val)).sqrMagnitude >= 4096f) { int num = ForceRefresh(instance2, characterID); DelayedRefreshes[characterID] = realtimeSinceStartup + 0.75f; BetterNetworking10.Log.Message($"Portal ghost refresh queued for {SafePlayerName(player.m_name)} ({characterID}) after {((Vector3)(ref val)).magnitude:F1} m movement; linked effects={num}"); } } if (DelayedRefreshes.TryGetValue(characterID, out var value2) && realtimeSinceStartup >= value2) { ForceRefresh(instance2, characterID); DelayedRefreshes.Remove(characterID); } LastPositions[characterID] = position; } TemporaryIds.Clear(); foreach (ZDOID key in LastPositions.Keys) { if (!ActivePlayers.Contains(key)) { TemporaryIds.Add(key); } } foreach (ZDOID temporaryId in TemporaryIds) { LastPositions.Remove(temporaryId); DelayedRefreshes.Remove(temporaryId); } } catch (Exception ex) { _runtimeDisabled = true; ClearRuntimeState(); BetterNetworking10.Log.Error("FEATURE FAILED Portal ghost fix: " + ex.GetType().Name + ": " + ex.Message + ". Disabled until restart; networking remains otherwise unchanged"); } } internal static void Clear() { ClearRuntimeState(); _externalModInstalled = false; _runtimeDisabled = false; } private static int ForceRefresh(ZDOMan manager, ZDOID characterId) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) manager.ForceSendZDO(characterId); int num = 0; List<ZDOID> allZDOIDsWithHash = ZDOExtraData.GetAllZDOIDsWithHash((Type)4, ZDOVars.s_ownerZDOUserId); foreach (ZDOID item in allZDOIDsWithHash) { if (!(item == characterId)) { ZDO zDO = manager.GetZDO(item); if (zDO != null && zDO.GetLong(ZDOVars.s_ownerZDOUserId, 0L) == ((ZDOID)(ref characterId)).UserID && zDO.GetLong(ZDOVars.s_ownerZDOId, 0L) == ((ZDOID)(ref characterId)).ID) { manager.ForceSendZDO(item); num++; } } } return num; } private static void ClearRuntimeState() { LastPositions.Clear(); DelayedRefreshes.Clear(); ActivePlayers.Clear(); TemporaryIds.Clear(); _manager = null; _nextCheck = 0f; } private static string SafePlayerName(string name) { return string.IsNullOrEmpty(name) ? "unknown player" : name; } } internal static class VersionInfo { public const string Version = "1.3.1"; } } namespace Costura { [CompilerGenerated] internal static class AssemblyLoader { private static object nullCacheLock = new object(); private static Dictionary<string, bool> nullCache = new Dictionary<string, bool>(); private static Dictionary<string, string> assemblyNames = new Dictionary<string, string>(); private static Dictionary<string, string> symbolNames = new Dictionary<string, string>(); private static int isAttached; private static string CultureToString(CultureInfo culture) { if (culture == null) { return ""; } return culture.Name; } private static Assembly ReadExistingAssembly(AssemblyName name) { AppDomain currentDomain = AppDomain.CurrentDomain; Assembly[] assemblies = currentDomain.GetAssemblies(); Assembly[] array = assemblies; foreach (Assembly assembly in array) { AssemblyName name2 = assembly.GetName(); if (string.Equals(name2.Name, name.Name, StringComparison.InvariantCultureIgnoreCase) && string.Equals(CultureToString(name2.CultureInfo), CultureToString(name.CultureInfo), StringComparison.InvariantCultureIgnoreCase)) { return assembly; } } return null; } private static void CopyTo(Stream source, Stream destination) { byte[] array = new byte[81920]; int count; while ((count = source.Read(array, 0, array.Length)) != 0) { destination.Write(array, 0, count); } } private static Stream LoadStream(string fullName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); if (fullName.EndsWith(".compressed")) { using (Stream stream = executingAssembly.GetManifestResourceStream(fullName)) { using DeflateStream source = new DeflateStream(stream, CompressionMode.Decompress); MemoryStream memoryStream = new MemoryStream(); CopyTo(source, memoryStream); memoryStream.Position = 0L; return memoryStream; } } return executingAssembly.GetManifestResourceStream(fullName); } private static Stream LoadStream(Dictionary<string, string> resourceNames, string name) { if (resourceNames.TryGetValue(name, out var value)) { return LoadStream(value); } return null; } private static byte[] ReadStream(Stream stream) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); return array; } private static Assembly ReadFromEmbeddedResources(Dictionary<string, string> assemblyNames, Dictionary<string, string> symbolNames, AssemblyName requestedAssemblyName) { string text = requestedAssemblyName.Name.ToLowerInvariant(); if (requestedAssemblyName.CultureInfo != null && !string.IsNullOrEmpty(requestedAssemblyName.CultureInfo.Name)) { text = requestedAssemblyName.CultureInfo.Name + "." + text; } byte[] rawAssembly; using (Stream stream = LoadStream(assemblyNames, text)) { if (stream == null) { return null; } rawAssembly = ReadStream(stream); } using (Stream stream2 = LoadStream(symbolNames, text)) { if (stream2 != null) { byte[] rawSymbolStore = ReadStream(stream2); return Assembly.Load(rawAssembly, rawSymbolStore); } } return Assembly.Load(rawAssembly); } public static Assembly ResolveAssembly(object sender, ResolveEventArgs e) { lock (nullCacheLock) { if (nullCache.ContainsKey(e.Name)) { return null; } } AssemblyName assemblyName = new AssemblyName(e.Name); Assembly assembly = ReadExistingAssembly(assemblyName); if ((object)assembly != null) { return assembly; } assembly = ReadFromEmbeddedResources(assemblyNames, symbolNames, assemblyName); if ((object)assembly == null) { lock (nullCacheLock) { nullCache[e.Name] = true; } if ((assemblyName.Flags & AssemblyNameFlags.Retargetable) != AssemblyNameFlags.None) { assembly = Assembly.Load(assemblyName); } } return assembly; } static AssemblyLoader() { assemblyNames.Add("costura", "costura.costura.dll.compressed"); symbolNames.Add("costura", "costura.costura.pdb.compressed"); assemblyNames.Add("system.buffers", "costura.system.buffers.dll.compressed"); assemblyNames.Add("system.diagnostics.diagnosticsource", "costura.system.diagnostics.diagnosticsource.dll.compressed"); assemblyNames.Add("system.memory", "costura.system.memory.dll.compressed"); assemblyNames.Add("system.numerics.vectors", "costura.system.numerics.vectors.dll.compressed"); assemblyNames.Add("system.runtime.compilerservices.unsafe", "costura.system.runtime.compilerservices.unsafe.dll.compressed"); assemblyNames.Add("system.threading.tasks.extensions", "costura.system.threading.tasks.extensions.dll.compressed"); assemblyNames.Add("zstdsharp", "costura.zstdsharp.dll.compressed"); } public static void Attach() { if (Interlocked.Exchange(ref isAttached, 1) == 1) { return; } AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e) { lock (nullCacheLock) { if (nullCache.ContainsKey(e.Name)) { return (Assembly)null; } } AssemblyName assemblyName = new AssemblyName(e.Name); Assembly assembly = ReadExistingAssembly(assemblyName); if ((object)assembly != null) { return assembly; } assembly = ReadFromEmbeddedResources(assemblyNames, symbolNames, assemblyName); if ((object)assembly == null) { lock (nullCacheLock) { nullCache[e.Name] = true; } if ((assemblyName.Flags & AssemblyNameFlags.Retargetable) != AssemblyNameFlags.None) { assembly = Assembly.Load(assemblyName); } } return assembly; }; } } } internal class DITBetterNetworking10_ProcessedByFody { internal const string FodyVersion = "6.9.3.0"; internal const string Costura = "5.7.0"; }