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.1.1
patchers/FiresSteamworksPatcher.dll
Decompiled a month 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.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("FiresSteamworksPatcher")] [assembly: AssemblyDescription("BepInEx preloader patcher for FiresGhettoNetworking. (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) for more per-peer ZDO flush headroom. Runs on both dedicated servers and clients wherever FGN is installed.")] [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.1.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.1.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace 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 (!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>(); } Log.LogInfo((object)("FiresGhettoNetworking detected — patcher will run on this " + (IsDedicatedServer() ? "dedicated server" : "client") + " install.")); 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 (!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 path = Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty; string text = Path.GetFileNameWithoutExtension(path).ToLowerInvariant(); string text2 = Path.GetDirectoryName(path)?.ToLowerInvariant() ?? string.Empty; if (text.Contains("server") || text2.Contains("server") || text2.Contains("dedicated")) { _isDedicatedServer = true; return true; } _isDedicatedServer = false; } catch (Exception ex) { Log.LogInfo((object)("Could not read process info (" + 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<FieldDefinition> enumerator = enumType.Fields.GetEnumerator(); try { while (enumerator.MoveNext()) { if (((MemberReference)enumerator.Current).Name == name) { return true; } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).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_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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/*cast due to .constrained prefix*/).Dispose(); } return null; } private static bool IsQueueCapConstantAt(Collection<Instruction> instructions, int index, out int value) { //IL_000c: 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) 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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) if (instruction.OpCode != OpCodes.Call && instruction.OpCode != OpCodes.Callvirt) { return false; } object operand = instruction.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val != null) { return ((MemberReference)val).Name == methodName; } return false; } } }