using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
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: AssemblyCompany("Rombusz")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Reduces PEAK character lifecycle hitches caused by initialization races and repeated diagnostic exceptions.")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("CrossplayStutterFix")]
[assembly: AssemblyTitle("CrossplayStutterFix")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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]
[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;
}
}
[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 CrossplayStutterFix
{
[BepInPlugin("Rombusz.CrossplayStutterFix", "CrossplayStutterFix", "1.1.0")]
public sealed class Plugin : BaseUnityPlugin
{
public const string Guid = "Rombusz.CrossplayStutterFix";
public const string Name = "CrossplayStutterFix";
public const string Version = "1.1.0";
private Harmony? _harmony;
private void Awake()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
_harmony = new Harmony("Rombusz.CrossplayStutterFix");
_harmony.PatchAll();
((BaseUnityPlugin)this).Logger.LogMessage((object)"Plugin CrossplayStutterFix 1.1.0 is loaded!");
}
private void OnDestroy()
{
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
[HarmonyPatch(typeof(CharacterData))]
internal static class CharacterDataRegistryPatch
{
private static readonly FieldRef<CharacterData, PhotonView> View = AccessTools.FieldRefAccess<CharacterData, PhotonView>("m_photonView");
private static readonly FieldRef<Dictionary<Player, CharacterData>> Instances = AccessTools.StaticFieldRefAccess<Dictionary<Player, CharacterData>>(AccessTools.Field(typeof(CharacterData), "m_instances"));
[HarmonyPostfix]
[HarmonyPatch("Awake")]
private static void RegisterNewestCharacter(CharacterData __instance)
{
PhotonView val = View.Invoke(__instance);
Dictionary<Player, CharacterData> dictionary = Instances.Invoke();
if (((val != null) ? val.Owner : null) != null && dictionary != null)
{
dictionary[val.Owner] = __instance;
VoiceDataInitializationPatch.AllowCommunication(__instance);
}
}
[HarmonyPrefix]
[HarmonyPatch("OnDestroy")]
private static bool RemoveOnlyCurrentCharacter(CharacterData __instance)
{
PhotonView val = View.Invoke(__instance);
Dictionary<Player, CharacterData> dictionary = Instances.Invoke();
if (((val != null) ? val.Owner : null) != null && dictionary != null && dictionary.TryGetValue(val.Owner, out var value) && value == __instance)
{
dictionary.Remove(val.Owner);
}
return false;
}
}
[HarmonyPatch(typeof(CharacterVoiceHandler))]
internal static class VoiceDataInitializationPatch
{
[HarmonyPrefix]
[HarmonyPatch("CheckCommunicationWithUser")]
private static bool InitializePlayer(Player p)
{
CharacterData data = default(CharacterData);
if (p != null && CharacterData.TryGetPlayerData(p, ref data))
{
AllowCommunication(data);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch("CheckCommunicationWithCharacter")]
private static bool InitializeCharacter(Character c)
{
if ((Object)(object)c != (Object)null)
{
InitializePlayer(((MonoBehaviourPun)c).photonView.Controller);
}
return false;
}
internal static void AllowCommunication(CharacterData data)
{
data.canCommunicateWith = true;
data.isMuted = false;
}
}
[HarmonyPatch(typeof(Character), "WarpPlayer")]
internal static class CharacterWarpPatch
{
private static readonly MethodInfo LogError = AccessTools.Method(typeof(Debug), "LogError", new Type[1] { typeof(object) }, (Type[])null);
private static readonly MethodInfo StopAnyClimbing = AccessTools.Method(typeof(CharacterClimbing), "StopAnyClimbing", (Type[])null, (Type[])null);
private static readonly MethodInfo StopClimbingWhenReady = AccessTools.Method(typeof(CharacterWarpPatch), "StopClimbingIfInitialized", (Type[])null, (Type[])null);
private static readonly FieldRef<CharacterClimbing, Character> ClimbingCharacter = AccessTools.FieldRefAccess<CharacterClimbing, Character>("character");
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> RepairEarlyWarpAndRemoveErrorStack(IEnumerable<CodeInstruction> instructions)
{
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, StopAnyClimbing))
{
instruction.opcode = OpCodes.Call;
instruction.operand = StopClimbingWhenReady;
}
else if (CodeInstructionExtensions.Calls(instruction, LogError))
{
instruction.opcode = OpCodes.Pop;
instruction.operand = null;
}
yield return instruction;
}
}
private static void StopClimbingIfInitialized(CharacterClimbing climbing)
{
if ((Object)(object)climbing != (Object)null && (Object)(object)ClimbingCharacter.Invoke(climbing) != (Object)null)
{
climbing.StopAnyClimbing();
}
}
}
[HarmonyPatch(typeof(AnimatedMouth), "Start")]
internal static class MalformedGhostMouthPatch
{
[HarmonyPrefix]
private static bool DisableIfAudioSourceIsMissing(AnimatedMouth __instance)
{
if (!__instance.isGhost || (Object)(object)__instance.audioSource != (Object)null)
{
return true;
}
((Behaviour)__instance).enabled = false;
return false;
}
}
[HarmonyPatch(typeof(Dynamite), "TestLightWick")]
internal static class DynamiteProximityPatch
{
private static Character? _readyCharacter;
[HarmonyPrefix]
private static bool RunWhenLocalCharacterIsUsable()
{
Character localCharacter = Character.localCharacter;
if ((Object)(object)localCharacter == (Object)null)
{
return false;
}
if ((Object)(object)localCharacter == (Object)(object)_readyCharacter)
{
return true;
}
if (localCharacter.refs != null && (Object)(object)localCharacter.refs.ragdoll != (Object)null && localCharacter.refs.ragdoll.partDict.TryGetValue((BodypartType)2, out var value) && (Object)(object)value != (Object)null && (Object)(object)value.transform != (Object)null)
{
_readyCharacter = localCharacter;
return true;
}
return false;
}
}
[HarmonyPatch(typeof(Character), "RPCA_Fall")]
internal static class FallDiagnosticPatch
{
private static readonly MethodInfo Log = AccessTools.Method(typeof(Debug), "Log", new Type[1] { typeof(object) }, (Type[])null);
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> RemoveRepeatedFallLog(IEnumerable<CodeInstruction> instructions)
{
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, Log))
{
instruction.opcode = OpCodes.Pop;
instruction.operand = null;
}
yield return instruction;
}
}
}
[HarmonyPatch(typeof(CharacterStats), "Record")]
internal static class ReviveTimelineDiagnosticPatch
{
private static readonly MethodInfo LogError = AccessTools.Method(typeof(Debug), "LogError", new Type[1] { typeof(object) }, (Type[])null);
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> RemoveReviveErrorStack(IEnumerable<CodeInstruction> instructions)
{
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, LogError))
{
instruction.opcode = OpCodes.Pop;
instruction.operand = null;
}
yield return instruction;
}
}
}
}