using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FishNet; using FishNet.Managing; using HarmonyLib; using Microsoft.CodeAnalysis; using SpongeMods.ModMenu; using Steamworks; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("FishNet.Runtime")] [assembly: AssemblyCompany("SpongeMods")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Larger lobbies and steadier connections.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a149c533da6d929b7267867242f5011f9c2152dc")] [assembly: AssemblyProduct("SpongeMods.BetterMultiplayer")] [assembly: AssemblyTitle("SpongeMods.BetterMultiplayer")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SpongeMods.BetterMultiplayer { internal static class Connections { private static NetworkManager _applied; public static void Apply() { NetworkManager networkManager = InstanceFinder.NetworkManager; if ((Object)(object)networkManager == (Object)null) { _applied = null; } else { if (networkManager == _applied) { return; } _applied = networkManager; if (Plugin.PatientTimeouts.Value) { ushort num = (ushort)Plugin.TimeoutSeconds.Value; if ((Object)(object)networkManager.ServerManager != (Object)null) { networkManager.ServerManager.SetRemoteClientTimeout((RemoteTimeoutType)1, num); } if ((Object)(object)networkManager.ClientManager != (Object)null) { networkManager.ClientManager.SetRemoteServerTimeout((RemoteTimeoutType)1, num); } Plugin.Log.LogInfo((object)$"Connection timeout set to {num}s."); } } } } internal static class Capacity { public static int Wanted => Plugin.MaxPlayers.Value; } [HarmonyPatch(typeof(SteamManager), "CreateLobby")] internal static class SteamLobbyCapacityPatch { private static bool Prefix() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) SteamMatchmaking.CreateLobby((ELobbyType)((SaveManager.CurServerSave == null || SaveManager.CurServerSave.IsPublic) ? 1 : 0), Capacity.Wanted); return false; } } [HarmonyPatch(typeof(ConnectionManager), "CreateOnlineLobby")] internal static class ServerCapacityPatch { private static void Prefix(ref int maxPlayers) { int wanted = Capacity.Wanted; if (wanted > maxPlayers) { Plugin.Log.LogInfo((object)$"Raising the player cap from {maxPlayers} to {wanted}."); maxPlayers = wanted; } } } [BepInPlugin("SpongeMods.BetterMultiplayer", "Sponge's Better Multiplayer Experience", "1.0.0")] [BepInDependency("SpongeMods.ModMenu", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string Id = "SpongeMods.BetterMultiplayer"; public const string Version = "1.0.0"; internal static ConfigEntry MaxPlayers; internal static ConfigEntry PatientTimeouts; internal static ConfigEntry TimeoutSeconds; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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 //IL_0099: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; MaxPlayers = ((BaseUnityPlugin)this).Config.Bind("Lobby", "Max players", 12, new ConfigDescription("How many players a lobby you host can hold. The stock limit is 8. Only the host needs this mod. Raising it a long way is not free: the game's interface was laid out for eight, and more players means more to keep in sync.", (AcceptableValueBase)(object)new AcceptableValueRange(2, 32), Array.Empty())); PatientTimeouts = ((BaseUnityPlugin)this).Config.Bind("Connection", "Patient timeouts", true, "Wait longer before dropping a player who has gone quiet, so an ordinary loading stall does not disconnect them."); TimeoutSeconds = ((BaseUnityPlugin)this).Config.Bind("Connection", "Timeout seconds", 60, new ConfigDescription("How long a peer may go quiet before it is dropped.", (AcceptableValueBase)(object)new AcceptableValueRange(5, 600), Array.Empty())); try { new Harmony("SpongeMods.BetterMultiplayer").PatchAll(); } catch (Exception ex) { Log.LogError((object)("Lobby size could not be raised: " + ex.Message)); } Tabs.Register(); Log.LogInfo((object)"Better Multiplayer ready."); } private void Update() { Connections.Apply(); } } internal static class Tabs { public static void Register() { SpongeMenu.Tab("SpongeMods.BetterMultiplayer", "Multiplayer", 50).Heading("Lobby").Number("Players", Plugin.MaxPlayers) .OnlyHost() .Note("Takes effect for the next lobby you host. A larger lobby means more of everything to keep in step, so raise it a little at a time and see how it holds up.") .Heading("Connection") .Toggle("Wait longer before dropping", Plugin.PatientTimeouts) .OnlyHost() .Number("Seconds", Plugin.TimeoutSeconds) .OnlyHost() .Note("How long a quiet connection is given before the host gives up on it. Worth raising for players on a slow link, at the cost of a genuinely dead connection lingering longer."); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }