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 LethalPisserNetworkFixExperimental v1.3.0
BepInEx/Plugins/LethalPisserNetworkFix[Experimental]/LethalPisserNetworkFix.dll
Decompiled 4 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LethalPisserNetworkFix")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LethalPisserNetworkFix")] [assembly: AssemblyTitle("LethalPisserNetworkFix")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace LethalPisserNetworkFix { [BepInPlugin("Potatoh.LethalPisserNetworkFix", "Lethal Pisser Network Fix", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "Potatoh.LethalPisserNetworkFix"; public const string PluginName = "Lethal Pisser Network Fix"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log = null; internal static readonly Dictionary<object, float> NextHeartbeatByInstance = new Dictionary<object, float>(); private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; new Harmony("Potatoh.LethalPisserNetworkFix").PatchAll(); Log.LogInfo((object)"Lethal Pisser Network Fix 1.0.0 loaded."); } } [HarmonyPatch] internal static class LethalPisserPatches { private const float HeartbeatInterval = 0.33f; private static readonly Type? OriginalType = AccessTools.TypeByName("LethalPisser.LethalPisserPlugin"); private static readonly FieldInfo? LocalPlayerIsPeeingField = ((OriginalType == null) ? null : AccessTools.Field(OriginalType, "localPlayerIsPeeing")); private static readonly MethodInfo? GetLocalPlayerMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "GetLocalPlayer", (Type[])null, (Type[])null)); private static readonly MethodInfo? SendPeeStateMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "SendPeeState", (Type[])null, (Type[])null)); private static readonly MethodInfo? TryReadStateMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "TryReadState", (Type[])null, (Type[])null)); private static readonly MethodInfo? SetPeeStateMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "SetPeeState", (Type[])null, (Type[])null)); private static readonly MethodInfo? BroadcastPeeStateMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "BroadcastPeeState", (Type[])null, (Type[])null)); private static readonly MethodInfo? FindPlayerByPlayerClientIdMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "FindPlayerByPlayerClientId", (Type[])null, (Type[])null)); [HarmonyTargetMethod] private static MethodBase? TargetUpdate() { return (OriginalType == null) ? null : AccessTools.Method(OriginalType, "Update", (Type[])null, (Type[])null); } [HarmonyPostfix] private static void UpdatePostfix(object __instance) { try { if (LocalPlayerIsPeeingField == null || GetLocalPlayerMethod == null || SendPeeStateMethod == null) { return; } if (!(bool)LocalPlayerIsPeeingField.GetValue(__instance)) { Plugin.NextHeartbeatByInstance.Remove(__instance); } else if (!(Time.time < GetNextHeartbeat(__instance))) { Plugin.NextHeartbeatByInstance[__instance] = Time.time + 0.33f; object? obj = GetLocalPlayerMethod.Invoke(null, null); PlayerControllerB val = (PlayerControllerB)((obj is PlayerControllerB) ? obj : null); if (!((Object)(object)val == (Object)null)) { SendPeeStateMethod.Invoke(__instance, new object[2] { val.playerClientId, true }); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Heartbeat postfix failed: " + ex.Message)); } } private static float GetNextHeartbeat(object instance) { float value; return Plugin.NextHeartbeatByInstance.TryGetValue(instance, out value) ? value : 0f; } } [HarmonyPatch] internal static class LethalPisserRequestPatch { private static readonly Type? OriginalType = AccessTools.TypeByName("LethalPisser.LethalPisserPlugin"); private static readonly MethodInfo? TryReadStateMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "TryReadState", (Type[])null, (Type[])null)); private static readonly MethodInfo? SetPeeStateMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "SetPeeState", (Type[])null, (Type[])null)); private static readonly MethodInfo? BroadcastPeeStateMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "BroadcastPeeState", (Type[])null, (Type[])null)); private static readonly MethodInfo? FindPlayerByPlayerClientIdMethod = ((OriginalType == null) ? null : AccessTools.Method(OriginalType, "FindPlayerByPlayerClientId", (Type[])null, (Type[])null)); [HarmonyTargetMethod] private static MethodBase? TargetHandleRequestMessage() { return (OriginalType == null) ? null : AccessTools.Method(OriginalType, "HandleRequestMessage", (Type[])null, (Type[])null); } [HarmonyPrefix] private static bool HandleRequestMessagePrefix(object __instance, ulong senderClientId, FastBufferReader reader) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) try { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return false; } if (TryReadStateMethod == null || SetPeeStateMethod == null || BroadcastPeeStateMethod == null || FindPlayerByPlayerClientIdMethod == null) { return true; } object[] array = new object[3] { reader, 0uL, false }; if (!(bool)TryReadStateMethod.Invoke(null, array)) { return false; } ulong num = (ulong)array[1]; bool flag = (bool)array[2]; object? obj = FindPlayerByPlayerClientIdMethod.Invoke(null, new object[1] { num }); PlayerControllerB val = (PlayerControllerB)((obj is PlayerControllerB) ? obj : null); if ((Object)(object)val == (Object)null) { return false; } bool flag2 = val.actualClientId == senderClientId; bool flag3 = val.playerClientId == senderClientId; if (!flag2 && !flag3) { Plugin.Log.LogWarning((object)($"Rejected pee request: playerClientId={num}, " + $"actualClientId={val.actualClientId}, senderClientId={senderClientId}")); return false; } SetPeeStateMethod.Invoke(__instance, new object[2] { num, flag }); BroadcastPeeStateMethod.Invoke(__instance, new object[2] { num, flag }); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("HandleRequestMessage prefix failed, falling back to original: " + ex.Message)); return true; } } } }