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 ServerSyncTimeout v1.0.0
ServerSyncTimeout.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ServerSyncTimeout")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ServerSyncTimeout")] [assembly: AssemblyTitle("ServerSyncTimeout")] [assembly: AssemblyVersion("1.0.0.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 ServerSyncTimeout { [BepInPlugin("com.dreich.serversynctimeout", "Server Sync Timeout", "1.0.0")] public class ServerSyncTimeoutPlugin : BaseUnityPlugin { public const string Guid = "com.dreich.serversynctimeout"; public const string Name = "Server Sync Timeout"; public const string Version = "1.0.0"; private const float DefaultTimeout = 300f; private const float MinTimeout = 30f; private const float MaxTimeout = 3600f; internal static ConfigEntry<float> Timeout; internal static ConfigEntry<float> ConnectionTimeout; internal static ManualLogSource Log; private void Awake() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Timeout = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Timeout", 300f, new ConfigDescription("Seconds the server keeps trying to send a mod's ServerSync config to a player before giving up and disconnecting them. ServerSync's own limit is 30. Changes apply straight away.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 3600f), Array.Empty<object>())); ConnectionTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("Connection", "Timeout", 300f, new ConfigDescription("Seconds without a reply from the other side before the game drops the connection. The game's own limit is 30 while playing and 90 while loading; this only ever makes it longer. Install on the server and every player for it to work both ways. Changes apply straight away.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 3600f), Array.Empty<object>())); } private void Start() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown int num = SyncTimeoutPatch.PatchAll(new Harmony("com.dreich.serversynctimeout")); Log.LogInfo((object)("Raised the config sending timeout in " + num + " mod(s).")); if (!ConnectionTimeoutPatch.Setup(new Harmony("com.dreich.serversynctimeout.connection"))) { Log.LogWarning((object)"Valheim has changed; the connection timeout can't be raised."); } } } internal static class ConnectionTimeoutPatch { private const string TimeoutField = "m_timeout"; private const string SetTimeoutMethod = "SetLongTimeout"; private static FieldRef<float> gameTimeout; private static float gameChoice; internal static bool Setup(Harmony harmony) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(ZRpc), "SetLongTimeout", (Type[])null, (Type[])null); FieldInfo fieldInfo = AccessTools.Field(typeof(ZRpc), "m_timeout"); if (methodInfo == null || fieldInfo == null || !fieldInfo.IsStatic || fieldInfo.FieldType != typeof(float)) { return false; } gameTimeout = AccessTools.StaticFieldRefAccess<float>(fieldInfo); gameChoice = gameTimeout.Invoke(); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(ConnectionTimeoutPatch), "AfterSetTimeout", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ServerSyncTimeoutPlugin.ConnectionTimeout.SettingChanged += delegate { Apply(); }; Apply(); return true; } private static void AfterSetTimeout() { gameChoice = gameTimeout.Invoke(); Apply(); } private static void Apply() { gameTimeout.Invoke() = Mathf.Max(gameChoice, ServerSyncTimeoutPlugin.ConnectionTimeout.Value); } } internal static class SyncTimeoutPatch { private const string ServerSyncNamespace = "ServerSync"; private const string ConfigSyncTypeName = "ConfigSync"; private const string WaitMethodMarker = "waitForQueue"; private const string StateMachineStep = "MoveNext"; private const float ServerSyncTimeout = 30f; private const string ServerSyncTimeoutText = "30 seconds"; private static readonly MethodInfo GameTime = AccessTools.PropertyGetter(typeof(Time), "time"); private static readonly MethodInfo CurrentTimeout = AccessTools.Method(typeof(SyncTimeoutPatch), "TimeoutSeconds", (Type[])null, (Type[])null); private static readonly MethodInfo RewriteMessage = AccessTools.Method(typeof(SyncTimeoutPatch), "Message", (Type[])null, (Type[])null); internal static int PatchAll(Harmony harmony) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown int num = 0; foreach (MethodInfo item in WaitMethods()) { try { harmony.Patch((MethodBase)item, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(SyncTimeoutPatch), "RaiseTimeout", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch (Exception ex) { ServerSyncTimeoutPlugin.Log.LogWarning((object)("Couldn't raise the timeout in " + item.DeclaringType.Assembly.GetName().Name + ": " + ex.Message)); } } return num; } private static IEnumerable<MethodInfo> WaitMethods() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.IsDynamic || assembly == typeof(SyncTimeoutPatch).Assembly) { continue; } foreach (Type item in TypesIn(assembly)) { if (IsServerSyncWait(item)) { MethodInfo methodInfo = AccessTools.Method(item, "MoveNext", (Type[])null, (Type[])null); if (methodInfo != null && Uses30SecondTimeout(methodInfo)) { yield return methodInfo; } } } } } private static IEnumerable<Type> TypesIn(Assembly assembly) { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type type) => type != null); } catch (Exception) { return Enumerable.Empty<Type>(); } } private static bool IsServerSyncWait(Type type) { if (!type.Name.Contains("waitForQueue")) { return false; } Type declaringType = type.DeclaringType; while (declaringType != null) { if (declaringType.Name == "ConfigSync" && declaringType.Namespace == "ServerSync") { return true; } declaringType = declaringType.DeclaringType; } return false; } private static bool Uses30SecondTimeout(MethodInfo step) { try { return PatchProcessor.GetOriginalInstructions((MethodBase)step, (ILGenerator)null).Any(IsServerSyncTimeout); } catch (Exception) { return false; } } private static bool IsServerSyncTimeout(CodeInstruction instruction) { if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num) { return num == 30f; } return false; } private static IEnumerable<CodeInstruction> RaiseTimeout(IEnumerable<CodeInstruction> instructions) { bool flag = false; foreach (CodeInstruction instruction in instructions) { if (flag && IsServerSyncTimeout(instruction)) { CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)CurrentTimeout); val.labels.AddRange(instruction.labels); val.blocks.AddRange(instruction.blocks); yield return val; } else { yield return instruction; } if (instruction.opcode == OpCodes.Ldstr && instruction.operand is string text && text.Contains("30 seconds")) { yield return new CodeInstruction(OpCodes.Call, (object)RewriteMessage); } flag = CodeInstructionExtensions.Calls(instruction, GameTime); } } private static float TimeoutSeconds() { return ServerSyncTimeoutPlugin.Timeout.Value; } private static string Message(string original) { return original.Replace("30 seconds", Mathf.RoundToInt(TimeoutSeconds()) + " seconds"); } } }