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 FiresSteamworksPatcher v1.0.0
FiresSteamworksPatcher.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("FiresSteamworksPatcher")] [assembly: AssemblyDescription("BepInEx preloader patcher. (1) Adds the missing Steam SDK 1.51+ recv-buffer enum members to Valheim's bundled com.rlabrecque.steamworks.net.dll so existing SetConfigValue paths can target them. (2) Bumps the ZDOMan.SendZDOs queue cap from vanilla 10240 to 102400 (10x) so per-peer ZDO flushes have more headroom on busy dedicated servers.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("FiresSteamworksPatcher")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("ee0f80de-6bd2-4a52-8997-bd60dce71b00")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] [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 FiresSteamworksPatcher { public static class FiresSteamworksPatcher { private const int ZdoSendQueueCapBytes = 102400; private const int VanillaZdoSendQueueCapBytes = 10240; private const int QueueSizeCallSearchRadius = 15; private const string SteamworksConfigEnumFullName = "Steamworks.ESteamNetworkingConfigValue"; private const string ZdoManTypeName = "ZDOMan"; private const string SendZdosMethodName = "SendZDOs"; private const string GetSendQueueSizeMethodName = "GetSendQueueSize"; private const string GhettoNetworkingDllGlob = "*GhettoNetwork*.dll"; private static readonly ManualLogSource Log = Logger.CreateLogSource("FiresSteamworksPatcher"); private static readonly (string Name, int Value)[] RecvBufferEnumMembers = new(string, int)[4] { ("k_ESteamNetworkingConfig_RecvBufferSize", 47), ("k_ESteamNetworkingConfig_RecvBufferMessages", 48), ("k_ESteamNetworkingConfig_RecvMaxMessageSize", 49), ("k_ESteamNetworkingConfig_RecvMaxSegmentsPerPacket", 50) }; private static bool? _ghettoNetworkingPresent; private static bool? _isDedicatedServer; public static IEnumerable<string> TargetDLLs { get { if (!IsDedicatedServer()) { Log.LogInfo((object)"Not running as a dedicated server — FiresSteamworksPatcher will not patch any assemblies. Both patches (Steam recv-buffer enum members and ZDOMan.SendZDOs queue cap) only affect server-side network behavior, so the patcher is no-op on client installs even when FGN is present."); return Array.Empty<string>(); } if (!IsGhettoNetworkingInstalled()) { Log.LogInfo((object)"FiresGhettoNetworking not detected in BepInEx/plugins/ — FiresSteamworksPatcher will not patch any assemblies. This patcher exists to support FiresGhettoNetworking's send-buffer + queue-cap features and has no other effect; without FGN there's nothing to do."); return Array.Empty<string>(); } return new string[2] { "com.rlabrecque.steamworks.net.dll", "assembly_valheim.dll" }; } } public static void Patch(AssemblyDefinition assembly) { AssemblyNameDefinition name = assembly.Name; string text = ((name != null) ? ((AssemblyNameReference)name).Name : null) ?? "<unknown>"; if (!IsDedicatedServer()) { Log.LogInfo((object)(text + ": not a dedicated server, leaving assembly untouched.")); return; } if (!IsGhettoNetworkingInstalled()) { Log.LogInfo((object)(text + ": FGN not present, leaving assembly untouched.")); return; } try { ModuleDefinition mainModule = assembly.MainModule; TypeDefinition type = mainModule.GetType("Steamworks.ESteamNetworkingConfigValue"); if (type != null) { AddMissingRecvBufferEnumMembers(type, text); } TypeDefinition type2 = mainModule.GetType("ZDOMan"); if (type2 != null) { RaiseSendZdosQueueCap(type2, text); } } catch (Exception arg) { Log.LogError((object)$"{text}: patch failed, server will run with vanilla behavior: {arg}"); } } private static bool IsDedicatedServer() { if (_isDedicatedServer.HasValue) { return _isDedicatedServer.Value; } try { string processName = Process.GetCurrentProcess().ProcessName; _isDedicatedServer = !string.IsNullOrEmpty(processName) && processName.IndexOf("server", StringComparison.OrdinalIgnoreCase) >= 0; } catch (Exception ex) { Log.LogInfo((object)("Could not read process name (" + ex.GetType().Name + ": " + ex.Message + "); treating as 'not a server'.")); _isDedicatedServer = false; } return _isDedicatedServer.Value; } private static bool IsGhettoNetworkingInstalled() { if (_ghettoNetworkingPresent.HasValue) { return _ghettoNetworkingPresent.Value; } try { string pluginPath = Paths.PluginPath; if (string.IsNullOrEmpty(pluginPath) || !Directory.Exists(pluginPath)) { _ghettoNetworkingPresent = false; return false; } string[] files = Directory.GetFiles(pluginPath, "*GhettoNetwork*.dll", SearchOption.AllDirectories); _ghettoNetworkingPresent = files.Length != 0; } catch (Exception ex) { Log.LogInfo((object)("Could not scan plugins directory (" + ex.GetType().Name + ": " + ex.Message + "); treating as 'FGN not present'.")); _ghettoNetworkingPresent = false; } return _ghettoNetworkingPresent.Value; } private static void AddMissingRecvBufferEnumMembers(TypeDefinition enumType, string assemblyName) { int num = 0; int num2 = 0; (string, int)[] recvBufferEnumMembers = RecvBufferEnumMembers; for (int i = 0; i < recvBufferEnumMembers.Length; i++) { (string, int) tuple = recvBufferEnumMembers[i]; if (EnumHasMember(enumType, tuple.Item1)) { num2++; continue; } enumType.Fields.Add(BuildEnumLiteral(enumType, tuple.Item1, tuple.Item2)); num++; } Log.LogInfo((object)$"{assemblyName}: Steamworks enum — added {num}, {num2} already present."); } private static FieldDefinition BuildEnumLiteral(TypeDefinition enumType, string name, int value) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown return new FieldDefinition(name, (FieldAttributes)32854, (TypeReference)(object)enumType) { Constant = value }; } private static bool EnumHasMember(TypeDefinition enumType, string name) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Enumerator<FieldDefinition> enumerator = enumType.Fields.GetEnumerator(); try { while (enumerator.MoveNext()) { FieldDefinition current = enumerator.Current; if (((MemberReference)current).Name == name) { return true; } } } finally { ((IDisposable)enumerator).Dispose(); } return false; } private static void RaiseSendZdosQueueCap(TypeDefinition zdoManType, string assemblyName) { MethodDefinition val = FindMethodByName(zdoManType, "SendZDOs"); if (val == null) { Log.LogWarning((object)(assemblyName + ": ZDOMan.SendZDOs not found; queue cap patch skipped.")); return; } Collection<Instruction> instructions = val.Body.Instructions; int num = 0; int num2 = 0; for (int i = 0; i < instructions.Count; i++) { if (IsQueueCapConstantAt(instructions, i, out var value)) { if (value >= 102400) { num2++; continue; } instructions[i].Operand = 102400; num++; } } if (num == 0 && num2 == 0) { Log.LogWarning((object)(assemblyName + ": no queue cap constant matched in ZDOMan.SendZDOs; vanilla behavior in effect.")); return; } Log.LogInfo((object)$"{assemblyName}: ZDOMan.SendZDOs queue cap — raised {num} to {102400}, {num2} already at target."); } private static MethodDefinition FindMethodByName(TypeDefinition type, string name) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator(); try { while (enumerator.MoveNext()) { MethodDefinition current = enumerator.Current; if (((MemberReference)current).Name == name) { return current; } } } finally { ((IDisposable)enumerator).Dispose(); } return null; } private static bool IsQueueCapConstantAt(Collection<Instruction> instructions, int index, out int value) { //IL_000d: 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) value = 0; Instruction val = instructions[index]; if (val.OpCode != OpCodes.Ldc_I4) { return false; } value = (int)val.Operand; if (value < 10240) { return false; } return IsNearGetSendQueueSizeCall(instructions, index); } private static bool IsNearGetSendQueueSizeCall(Collection<Instruction> instructions, int center) { int num = Math.Max(0, center - 15); int num2 = Math.Min(instructions.Count, center + 15 + 1); for (int i = num; i < num2; i++) { if (IsCallTo(instructions[i], "GetSendQueueSize")) { return true; } } return false; } private static bool IsCallTo(Instruction instruction, string methodName) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (instruction.OpCode != OpCodes.Call && instruction.OpCode != OpCodes.Callvirt) { return false; } object operand = instruction.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); return val != null && ((MemberReference)val).Name == methodName; } } }