using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using Unity.Collections;
using Unity.Netcode;
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("Unity.Netcode.Runtime")]
[assembly: AssemblyCompany("NicholaScott.BepInEx.RuntimeNetcodeRPCValidator")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.5.0")]
[assembly: AssemblyInformationalVersion("0.2.5+6e2f89b3631ae55d2f51a00ccfd3f20fec9d2372")]
[assembly: AssemblyProduct("RuntimeNetcodeRPCValidator")]
[assembly: AssemblyTitle("NicholaScott.BepInEx.RuntimeNetcodeRPCValidator")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace RuntimeNetcodeRPCValidator
{
public class AlreadyRegisteredException : Exception
{
public AlreadyRegisteredException(string PluginGUID)
: base("Can't register plugin " + PluginGUID + " until the other instance of NetcodeValidator is Disposed of!")
{
}
}
public class InvalidPluginGuidException : Exception
{
public InvalidPluginGuidException(string pluginGUID)
: base("Can't patch plugin " + pluginGUID + " because it doesn't exist!")
{
}
}
public class NotNetworkBehaviourException : Exception
{
public NotNetworkBehaviourException(Type type)
: base("Netcode Runtime RPC Validator tried to NetcodeValidator.Patch type " + type.Name + " that doesn't inherit from NetworkBehaviour!")
{
}
}
public class MustCallFromDeclaredTypeException : Exception
{
public MustCallFromDeclaredTypeException()
: base("Netcode Runtime RPC Validator tried to run NetcodeValidator.PatchAll from a delegate! You must call PatchAll from a declared type.")
{
}
}
public static class FastBufferExtensions
{
private const BindingFlags BindingAll = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private static void WriteSystemSerializable(this FastBufferWriter fastBufferWriter, object serializable)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
BinaryFormatter binaryFormatter = new BinaryFormatter();
using MemoryStream memoryStream = new MemoryStream();
binaryFormatter.Serialize(memoryStream, serializable);
byte[] array = memoryStream.ToArray();
int num = array.Length;
((FastBufferWriter)(ref fastBufferWriter)).WriteValueSafe<int>(ref num, default(ForPrimitives));
((FastBufferWriter)(ref fastBufferWriter)).WriteBytes(array, -1, 0);
}
private static void ReadSystemSerializable(this FastBufferReader fastBufferReader, out object serializable)
{
//IL_0006: 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)
int num = default(int);
((FastBufferReader)(ref fastBufferReader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
byte[] buffer = new byte[num];
((FastBufferReader)(ref fastBufferReader)).ReadBytes(ref buffer, num, 0);
using MemoryStream memoryStream = new MemoryStream(buffer);
memoryStream.Seek(0L, SeekOrigin.Begin);
BinaryFormatter binaryFormatter = new BinaryFormatter();
serializable = binaryFormatter.Deserialize(memoryStream);
}
private static void WriteNetcodeSerializable(this FastBufferWriter fastBufferWriter, object networkSerializable)
{
//IL_0010: 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)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(1024, (Allocator)2, -1);
try
{
BufferSerializer<BufferSerializerWriter> val2 = default(BufferSerializer<BufferSerializerWriter>);
val2..ctor(new BufferSerializerWriter(val));
object obj = ((networkSerializable is INetworkSerializable) ? networkSerializable : null);
if (obj != null)
{
((INetworkSerializable)obj).NetworkSerialize<BufferSerializerWriter>(val2);
}
byte[] array = ((FastBufferWriter)(ref val)).ToArray();
int num = array.Length;
((FastBufferWriter)(ref fastBufferWriter)).WriteValueSafe<int>(ref num, default(ForPrimitives));
((FastBufferWriter)(ref fastBufferWriter)).WriteBytes(array, -1, 0);
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
private static void ReadNetcodeSerializable(this FastBufferReader fastBufferReader, Type type, out object serializable)
{
//IL_0006: 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_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
int num = default(int);
((FastBufferReader)(ref fastBufferReader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
byte[] array = new byte[num];
((FastBufferReader)(ref fastBufferReader)).ReadBytes(ref array, num, 0);
FastBufferReader val = default(FastBufferReader);
((FastBufferReader)(ref val))..ctor(array, (Allocator)2, -1, 0);
try
{
BufferSerializer<BufferSerializerReader> val2 = default(BufferSerializer<BufferSerializerReader>);
val2..ctor(new BufferSerializerReader(val));
serializable = Activator.CreateInstance(type);
object obj = serializable;
object obj2 = ((obj is INetworkSerializable) ? obj : null);
if (obj2 != null)
{
((INetworkSerializable)obj2).NetworkSerialize<BufferSerializerReader>(val2);
}
}
finally
{
((IDisposable)(FastBufferReader)(ref val)).Dispose();
}
}
public static void WriteMethodInfoAndParameters(this FastBufferWriter fastBufferWriter, MethodBase methodInfo, object[] args)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
((FastBufferWriter)(ref fastBufferWriter)).WriteValueSafe(methodInfo.Name, false);
ParameterInfo[] parameters = methodInfo.GetParameters();
int num = parameters.Length;
((FastBufferWriter)(ref fastBufferWriter)).WriteValueSafe<int>(ref num, default(ForPrimitives));
for (int i = 0; i < parameters.Length; i++)
{
ParameterInfo parameterInfo = parameters[i];
object obj = args[i];
bool flag = obj == null || parameterInfo.ParameterType == typeof(ServerRpcParams) || parameterInfo.ParameterType == typeof(ClientRpcParams);
((FastBufferWriter)(ref fastBufferWriter)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
if (flag)
{
continue;
}
if (parameterInfo.ParameterType.GetInterfaces().Contains(typeof(INetworkSerializable)))
{
fastBufferWriter.WriteNetcodeSerializable(obj);
continue;
}
if (parameterInfo.ParameterType.IsSerializable)
{
fastBufferWriter.WriteSystemSerializable(obj);
continue;
}
throw new SerializationException(TextHandler.ObjectNotSerializable(parameterInfo));
}
}
public static MethodInfo ReadMethodInfoAndParameters(this FastBufferReader fastBufferReader, Type methodDeclaringType, ref object[] args)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
string name = default(string);
((FastBufferReader)(ref fastBufferReader)).ReadValueSafe(ref name, false);
int num = default(int);
((FastBufferReader)(ref fastBufferReader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
MethodInfo method = methodDeclaringType.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (num != method?.GetParameters().Length)
{
throw new Exception(TextHandler.InconsistentParameterCount(method, num));
}
bool flag = default(bool);
for (int i = 0; i < num; i++)
{
((FastBufferReader)(ref fastBufferReader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
if (flag)
{
continue;
}
ParameterInfo parameterInfo = method.GetParameters()[i];
object serializable;
if (parameterInfo.ParameterType.GetInterfaces().Contains(typeof(INetworkSerializable)))
{
fastBufferReader.ReadNetcodeSerializable(parameterInfo.ParameterType, out serializable);
}
else
{
if (!parameterInfo.ParameterType.IsSerializable)
{
throw new SerializationException(TextHandler.ObjectNotSerializable(parameterInfo));
}
fastBufferReader.ReadSystemSerializable(out serializable);
}
args[i] = serializable;
}
return method;
}
}
public sealed class NetcodeValidator : IDisposable
{
private static readonly List<string> AlreadyRegistered = new List<string>();
internal const string TypeCustomMessageHandlerPrefix = "Net";
private static List<(NetcodeValidator validator, Type custom, Type native)> BoundNetworkObjects { get; } = new List<(NetcodeValidator, Type, Type)>();
private List<string> CustomMessageHandlers { get; }
private Harmony Patcher { get; }
public string PluginGuid { get; }
internal static event Action<NetcodeValidator, Type> AddedNewBoundBehaviour;
private event Action<string> AddedNewCustomMessageHandler;
public NetcodeValidator(string pluginGuid)
{
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
if (!Chainloader.PluginInfos.TryGetValue(pluginGuid, out var _))
{
throw new InvalidPluginGuidException(pluginGuid);
}
if (AlreadyRegistered.Contains(pluginGuid))
{
throw new AlreadyRegisteredException(pluginGuid);
}
AlreadyRegistered.Add(pluginGuid);
PluginGuid = pluginGuid;
CustomMessageHandlers = new List<string>();
Patcher = new Harmony(pluginGuid + "NicholaScott.BepInEx.RuntimeNetcodeRPCValidator");
Plugin.NetworkManagerInitialized += NetworkManagerInitialized;
Plugin.NetworkManagerShutdown += NetworkManagerShutdown;
}
internal static void TryLoadRelatedComponentsInOrder(NetworkBehaviour __instance, MethodBase __originalMethod)
{
foreach (var item in from obj in BoundNetworkObjects
where obj.native == __originalMethod.DeclaringType
select obj into it
orderby it.validator.PluginGuid
select it)
{
Plugin.Logger.LogInfo((object)TextHandler.CustomComponentAddedToExistingObject(item, __originalMethod));
Component obj2 = ((Component)__instance).gameObject.AddComponent(item.custom);
((NetworkBehaviour)(object)((obj2 is NetworkBehaviour) ? obj2 : null)).SyncWithNetworkObject();
}
}
private bool Patch(MethodInfo rpcMethod, out bool isServerRpc, out bool isClientRpc)
{
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Expected O, but got Unknown
isServerRpc = ((MemberInfo)rpcMethod).GetCustomAttributes<ServerRpcAttribute>().Any();
isClientRpc = ((MemberInfo)rpcMethod).GetCustomAttributes<ClientRpcAttribute>().Any();
bool flag = rpcMethod.Name.EndsWith("ServerRpc");
bool flag2 = rpcMethod.Name.EndsWith("ClientRpc");
if (!isClientRpc && !isServerRpc && !flag2 && !flag)
{
return false;
}
if ((!isServerRpc && flag) || (!isClientRpc && flag2))
{
Plugin.Logger.LogError((object)TextHandler.MethodLacksRpcAttribute(rpcMethod));
return false;
}
if ((isServerRpc && !flag) || (isClientRpc && !flag2))
{
Plugin.Logger.LogError((object)TextHandler.MethodLacksSuffix(rpcMethod));
return false;
}
Patcher.Patch((MethodBase)rpcMethod, new HarmonyMethod(typeof(NetworkBehaviourExtensions), "MethodPatch", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
return true;
}
public void BindToPreExistingObjectByBehaviour<TCustomBehaviour, TNativeBehaviour>() where TCustomBehaviour : NetworkBehaviour where TNativeBehaviour : NetworkBehaviour
{
if (Object.op_Implicit((Object)(object)NetworkManager.Singleton) && (NetworkManager.Singleton.IsListening || NetworkManager.Singleton.IsConnectedClient))
{
Plugin.Logger.LogError((object)TextHandler.PluginTriedToBindToPreExistingObjectTooLate(this, typeof(TCustomBehaviour), typeof(TNativeBehaviour)));
}
else
{
OnAddedNewBoundBehaviour(this, typeof(TCustomBehaviour), typeof(TNativeBehaviour));
}
}
public void Patch(Type netBehaviourTyped)
{
if (netBehaviourTyped.BaseType != typeof(NetworkBehaviour))
{
throw new NotNetworkBehaviourException(netBehaviourTyped);
}
OnAddedNewCustomMessageHandler("Net." + netBehaviourTyped.Name);
int num = 0;
int num2 = 0;
MethodInfo[] methods = netBehaviourTyped.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo rpcMethod in methods)
{
if (Patch(rpcMethod, out var isServerRpc, out var isClientRpc))
{
num += (isServerRpc ? 1 : 0);
num2 += (isClientRpc ? 1 : 0);
}
}
Plugin.Logger.LogInfo((object)TextHandler.SuccessfullyPatchedType(netBehaviourTyped, num, num2));
}
public void Patch(Assembly assembly)
{
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.BaseType == typeof(NetworkBehaviour))
{
Patch(type);
}
}
}
public void PatchAll()
{
Assembly assembly = new StackTrace().GetFrame(1).GetMethod().ReflectedType?.Assembly;
if (assembly == null)
{
throw new MustCallFromDeclaredTypeException();
}
Patch(assembly);
}
public void UnpatchSelf()
{
Plugin.Logger.LogInfo((object)TextHandler.PluginUnpatchedAllRPCs(this));
Patcher.UnpatchSelf();
}
private static void RegisterMessageHandlerWithNetworkManager(string handler)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler(handler, new HandleNamedMessageDelegate(NetworkBehaviourExtensions.ReceiveNetworkMessage));
}
private void NetworkManagerInitialized()
{
AddedNewCustomMessageHandler += RegisterMessageHandlerWithNetworkManager;
foreach (string customMessageHandler in CustomMessageHandlers)
{
RegisterMessageHandlerWithNetworkManager(customMessageHandler);
}
}
private void NetworkManagerShutdown()
{
AddedNewCustomMessageHandler -= RegisterMessageHandlerWithNetworkManager;
foreach (string customMessageHandler in CustomMessageHandlers)
{
NetworkManager.Singleton.CustomMessagingManager.UnregisterNamedMessageHandler(customMessageHandler);
}
}
public void Dispose()
{
Plugin.NetworkManagerInitialized -= NetworkManagerInitialized;
Plugin.NetworkManagerShutdown -= NetworkManagerShutdown;
AlreadyRegistered.Remove(PluginGuid);
if (Object.op_Implicit((Object)(object)NetworkManager.Singleton))
{
NetworkManagerShutdown();
}
if (Patcher.GetPatchedMethods().Any())
{
UnpatchSelf();
}
}
private void OnAddedNewCustomMessageHandler(string obj)
{
CustomMessageHandlers.Add(obj);
this.AddedNewCustomMessageHandler?.Invoke(obj);
}
private static void OnAddedNewBoundBehaviour(NetcodeValidator validator, Type custom, Type native)
{
BoundNetworkObjects.Add((validator, custom, native));
NetcodeValidator.AddedNewBoundBehaviour?.Invoke(validator, native);
}
}
public static class NetworkBehaviourExtensions
{
public enum RpcState
{
FromUser,
FromNetworking
}
private static RpcState RpcSource;
public static ClientRpcParams CreateSendToFromReceived(this ServerRpcParams senderId)
{
//IL_0002: 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_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
ClientRpcParams result = default(ClientRpcParams);
result.Send = new ClientRpcSendParams
{
TargetClientIds = new ulong[1] { senderId.Receive.SenderClientId }
};
return result;
}
public static void SyncWithNetworkObject(this NetworkBehaviour networkBehaviour)
{
if (!networkBehaviour.NetworkObject.ChildNetworkBehaviours.Contains(networkBehaviour))
{
networkBehaviour.NetworkObject.ChildNetworkBehaviours.Add(networkBehaviour);
}
networkBehaviour.UpdateNetworkProperties();
}
private static bool ValidateRPCMethod(NetworkBehaviour networkBehaviour, MethodBase method, RpcState state, out RpcAttribute rpcAttribute)
{
bool flag = ((MemberInfo)method).GetCustomAttributes<ServerRpcAttribute>().Any();
bool flag2 = ((MemberInfo)method).GetCustomAttributes<ClientRpcAttribute>().Any();
bool num = flag && ((MemberInfo)method).GetCustomAttribute<ServerRpcAttribute>().RequireOwnership;
rpcAttribute = (RpcAttribute)(flag ? ((object)((MemberInfo)method).GetCustomAttribute<ServerRpcAttribute>()) : ((object)((MemberInfo)method).GetCustomAttribute<ClientRpcAttribute>()));
if (num && networkBehaviour.OwnerClientId != NetworkManager.Singleton.LocalClientId)
{
Plugin.Logger.LogError((object)TextHandler.NotOwnerOfNetworkObject((state == RpcState.FromUser) ? "We" : "Client", method, networkBehaviour.NetworkObject));
return false;
}
if (state == RpcState.FromUser && flag2 && !NetworkManager.Singleton.IsServer && !NetworkManager.Singleton.IsHost)
{
Plugin.Logger.LogError((object)TextHandler.CantRunClientRpcFromClient(method));
return false;
}
if (state == RpcState.FromUser && !flag && !flag2)
{
Plugin.Logger.LogError((object)TextHandler.MethodPatchedButLacksAttributes(method));
return false;
}
if (state == RpcState.FromNetworking && !flag && !flag2)
{
Plugin.Logger.LogError((object)TextHandler.MethodPatchedAndNetworkCalledButLacksAttributes(method));
return false;
}
if (state == RpcState.FromNetworking && flag && !networkBehaviour.IsServer && !networkBehaviour.IsHost)
{
Plugin.Logger.LogError((object)TextHandler.CantRunServerRpcAsClient(method));
return false;
}
return true;
}
private static bool MethodPatchInternal(NetworkBehaviour networkBehaviour, MethodBase method, object[] args)
{
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
if (!Object.op_Implicit((Object)(object)NetworkManager.Singleton) || (!NetworkManager.Singleton.IsListening && !NetworkManager.Singleton.IsConnectedClient))
{
Plugin.Logger.LogError((object)TextHandler.NoNetworkManagerPresentToSendRpc(networkBehaviour));
return false;
}
RpcState rpcSource = RpcSource;
RpcSource = RpcState.FromUser;
if (rpcSource == RpcState.FromNetworking)
{
return true;
}
if (!ValidateRPCMethod(networkBehaviour, method, rpcSource, out var rpcAttribute))
{
return false;
}
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor((method.GetParameters().Length + 1) * 128, (Allocator)2, -1);
ulong networkObjectId = networkBehaviour.NetworkObjectId;
((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
ushort networkBehaviourId = networkBehaviour.NetworkBehaviourId;
((FastBufferWriter)(ref val)).WriteValueSafe<ushort>(ref networkBehaviourId, default(ForPrimitives));
val.WriteMethodInfoAndParameters(method, args);
string text = new StringBuilder("Net").Append(".").Append(method.DeclaringType.Name).ToString();
NetworkDelivery val2 = (NetworkDelivery)(((int)rpcAttribute.Delivery == 0) ? 2 : 0);
if (rpcAttribute is ServerRpcAttribute)
{
NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(text, 0uL, val, val2);
}
else
{
ParameterInfo[] parameters = method.GetParameters();
if (parameters.Length != 0 && parameters[^1].ParameterType == typeof(ClientRpcParams))
{
NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(text, ((ClientRpcParams)args[^1]).Send.TargetClientIds, val, val2);
}
else
{
NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll(text, val, val2);
}
}
return false;
}
internal static void ReceiveNetworkMessage(ulong sender, FastBufferReader reader)
{
//IL_0006: 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: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
ulong key = default(ulong);
((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref key, default(ForPrimitives));
ushort num = default(ushort);
((FastBufferReader)(ref reader)).ReadValueSafe<ushort>(ref num, default(ForPrimitives));
int position = ((FastBufferReader)(ref reader)).Position;
string text = default(string);
((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
((FastBufferReader)(ref reader)).Seek(position);
if (!NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(key, out var value))
{
Plugin.Logger.LogError((object)TextHandler.RpcCalledBeforeObjectSpawned());
return;
}
NetworkBehaviour networkBehaviourAtOrderIndex = value.GetNetworkBehaviourAtOrderIndex(num);
MethodInfo method = ((object)networkBehaviourAtOrderIndex).GetType().GetMethod(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
RpcAttribute rpcAttribute;
if (method == null)
{
Plugin.Logger.LogError((object)TextHandler.NetworkCalledNonExistentMethod(networkBehaviourAtOrderIndex, text));
}
else if (ValidateRPCMethod(networkBehaviourAtOrderIndex, method, RpcState.FromNetworking, out rpcAttribute))
{
RpcSource = RpcState.FromNetworking;
ParameterInfo[] parameters = method.GetParameters();
bool num2 = rpcAttribute is ServerRpcAttribute && parameters.Length != 0 && parameters[^1].ParameterType == typeof(ServerRpcParams);
object[] args = null;
if (parameters.Length != 0)
{
args = new object[parameters.Length];
}
reader.ReadMethodInfoAndParameters(method.DeclaringType, ref args);
if (num2)
{
args[^1] = (object)new ServerRpcParams
{
Receive = new ServerRpcReceiveParams
{
SenderClientId = sender
}
};
}
method.Invoke(networkBehaviourAtOrderIndex, args);
}
}
internal static bool MethodPatch(NetworkBehaviour __instance, MethodBase __originalMethod, object[] __args)
{
return MethodPatchInternal(__instance, __originalMethod, __args);
}
}
[BepInPlugin("NicholaScott.BepInEx.RuntimeNetcodeRPCValidator", "RuntimeNetcodeRPCValidator", "0.2.5")]
public class Plugin : BaseUnityPlugin
{
private readonly Harmony _harmony = new Harmony("NicholaScott.BepInEx.RuntimeNetcodeRPCValidator");
private List<Type> AlreadyPatchedNativeBehaviours { get; } = new List<Type>();
internal static ManualLogSource Logger { get; private set; }
public static event Action NetworkManagerInitialized;
public static event Action NetworkManagerShutdown;
private void Awake()
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
NetcodeValidator.AddedNewBoundBehaviour += NetcodeValidatorOnAddedNewBoundBehaviour;
_harmony.Patch((MethodBase)AccessTools.Method(typeof(NetworkManager), "Initialize", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "OnNetworkManagerInitialized", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
_harmony.Patch((MethodBase)AccessTools.Method(typeof(NetworkManager), "Shutdown", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "OnNetworkManagerShutdown", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
private void NetcodeValidatorOnAddedNewBoundBehaviour(NetcodeValidator validator, Type netBehaviour)
{
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Expected O, but got Unknown
if (!AlreadyPatchedNativeBehaviours.Contains(netBehaviour))
{
AlreadyPatchedNativeBehaviours.Add(netBehaviour);
MethodBase methodBase = AccessTools.Method(netBehaviour, "Awake", (Type[])null, (Type[])null);
if (methodBase == null)
{
methodBase = AccessTools.Method(netBehaviour, "Start", (Type[])null, (Type[])null);
}
if (methodBase == null)
{
methodBase = AccessTools.Constructor(netBehaviour, (Type[])null, false);
}
Logger.LogInfo((object)TextHandler.RegisteredPatchForType(validator, netBehaviour, methodBase));
HarmonyMethod val = new HarmonyMethod(typeof(NetcodeValidator), "TryLoadRelatedComponentsInOrder", (Type[])null);
_harmony.Patch(methodBase, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
protected static void OnNetworkManagerInitialized()
{
Plugin.NetworkManagerInitialized?.Invoke();
}
protected static void OnNetworkManagerShutdown()
{
Plugin.NetworkManagerShutdown?.Invoke();
}
}
internal static class TextHandler
{
private const string NoNetworkManagerPresentToSendRpcConst = "NetworkBehaviour {0} tried to send a RPC but the NetworkManager is non-existant!";
private const string MethodLacksAttributeConst = "Can't patch method {0}.{1} because it lacks a [{2}] attribute.";
private const string MethodLacksSuffixConst = "Can't patch method {0}.{1} because it's name doesn't end with '{2}'!";
private const string SuccessfullyPatchedTypeConst = "Patched {0} ServerRPC{1} & {2} ClientRPC{3} on NetworkBehaviour {4}.";
private const string NotOwnerOfNetworkObjectConst = "{0} tried to run ServerRPC {1} but not the owner of NetworkObject {2}";
private const string CantRunClientRpcFromClientConst = "Tried to run ClientRpc {0} but we're not a host! You should only call ClientRpc(s) from inside a ServerRpc OR if you've checked you're on the server with IsHost!";
private const string CantRunServerRpcAsClientConst = "Received message to run ServerRPC {0}.{1} but we're a client!";
private const string MethodPatchedButLacksAttributesConst = "Rpc Method {0} has been patched to attempt networking but lacks any RpcAttributes! This should never happen!";
private const string MethodPatchedAndNetworkCalledButLacksAttributesConst = "Rpc Method {0} has been patched && even received a network call to execute but lacks any RpcAttributes! This should never happen! Something is VERY fucky!!!";
private const string RpcCalledBeforeObjectSpawnedConst = "An RPC called on a NetworkObject that is not in the spawned objects list. Please make sure the NetworkObject is spawned before calling RPCs.";
private const string NetworkCalledNonExistentMethodConst = "NetworkBehaviour {0} received RPC {1} but that method doesn't exist on {2}!";
private const string ObjectNotSerializableConst = "[Network] Parameter ({0} {1}) is not marked [Serializable] nor does it implement INetworkSerializable!";
private const string InconsistentParameterCountConst = "[Network] NetworkBehaviour received a RPC {0} but the number of parameters sent {1} != MethodInfo param count {2}";
private const string PluginTriedToBindToPreExistingObjectTooLateConst = "Plugin '{0}' tried to bind {1} to {2} but it's too late! Make sure you bind to any pre-existing NetworkObjects before NetworkManager.IsListening || IsConnectedClient.";
private const string RegisteredPatchForTypeConst = "Successfully registered first patch for type {0}.{1} | Triggered by {2}";
private const string CustomComponentAddedToExistingObjectConst = "Successfully added {0} to {1} via {2}. Triggered by plugin {3}";
private const string PluginUnpatchedAllRPCsConst = "Plugin {0} has unpatched all RPCs!";
internal static string NoNetworkManagerPresentToSendRpc(NetworkBehaviour networkBehaviour)
{
return $"NetworkBehaviour {networkBehaviour.NetworkBehaviourId} tried to send a RPC but the NetworkManager is non-existant!";
}
internal static string MethodLacksRpcAttribute(MethodInfo method)
{
return string.Format("Can't patch method {0}.{1} because it lacks a [{2}] attribute.", method.DeclaringType?.Name, method.Name, method.Name.EndsWith("ServerRpc") ? "ServerRpc" : "ClientRpc");
}
internal static string MethodLacksSuffix(MethodBase method)
{
return string.Format("Can't patch method {0}.{1} because it's name doesn't end with '{2}'!", method.DeclaringType?.Name, method.Name, (((MemberInfo)method).GetCustomAttribute<ServerRpcAttribute>() != null) ? "ServerRpc" : "ClientRpc");
}
internal static string SuccessfullyPatchedType(Type networkType, int serverRpcCount, int clientRpcCount)
{
return string.Format("Patched {0} ServerRPC{1} & {2} ClientRPC{3} on NetworkBehaviour {4}.", serverRpcCount, (serverRpcCount == 1) ? "" : "s", clientRpcCount, (clientRpcCount == 1) ? "" : "s", networkType.Name);
}
internal static string NotOwnerOfNetworkObject(string whoIsNotOwner, MethodBase method, NetworkObject networkObject)
{
return $"{whoIsNotOwner} tried to run ServerRPC {method.Name} but not the owner of NetworkObject {networkObject.NetworkObjectId}";
}
internal static string CantRunClientRpcFromClient(MethodBase method)
{
return $"Tried to run ClientRpc {method.Name} but we're not a host! You should only call ClientRpc(s) from inside a ServerRpc OR if you've checked you're on the server with IsHost!";
}
internal static string CantRunServerRpcAsClient(MethodBase method)
{
return $"Received message to run ServerRPC {method.DeclaringType?.Name}.{method.Name} but we're a client!";
}
internal static string MethodPatchedButLacksAttributes(MethodBase method)
{
return $"Rpc Method {method.Name} has been patched to attempt networking but lacks any RpcAttributes! This should never happen!";
}
internal static string MethodPatchedAndNetworkCalledButLacksAttributes(MethodBase method)
{
return $"Rpc Method {method.Name} has been patched && even received a network call to execute but lacks any RpcAttributes! This should never happen! Something is VERY fucky!!!";
}
internal static string RpcCalledBeforeObjectSpawned()
{
return "An RPC called on a NetworkObject that is not in the spawned objects list. Please make sure the NetworkObject is spawned before calling RPCs.";
}
internal static string NetworkCalledNonExistentMethod(NetworkBehaviour networkBehaviour, string rpcName)
{
return $"NetworkBehaviour {networkBehaviour.NetworkBehaviourId} received RPC {rpcName} but that method doesn't exist on {((object)networkBehaviour).GetType().Name}!";
}
internal static string ObjectNotSerializable(ParameterInfo paramInfo)
{
return $"[Network] Parameter ({paramInfo.ParameterType.Name} {paramInfo.Name}) is not marked [Serializable] nor does it implement INetworkSerializable!";
}
internal static string InconsistentParameterCount(MethodBase method, int paramsSent)
{
return $"[Network] NetworkBehaviour received a RPC {method.Name} but the number of parameters sent {paramsSent} != MethodInfo param count {method.GetParameters().Length}";
}
internal static string PluginTriedToBindToPreExistingObjectTooLate(NetcodeValidator netcodeValidator, Type from, Type to)
{
return $"Plugin '{netcodeValidator.PluginGuid}' tried to bind {from.Name} to {to.Name} but it's too late! Make sure you bind to any pre-existing NetworkObjects before NetworkManager.IsListening || IsConnectedClient.";
}
internal static string RegisteredPatchForType(NetcodeValidator validator, Type netBehaviour, MethodBase method)
{
return $"Successfully registered first patch for type {netBehaviour.Name}.{method.Name} | Triggered by {validator.PluginGuid}";
}
internal static string CustomComponentAddedToExistingObject((NetcodeValidator validator, Type custom, Type native) it, MethodBase methodBase)
{
return $"Successfully added {it.custom.Name} to {it.native.Name} via {methodBase.Name}. Triggered by plugin {it.validator.PluginGuid}";
}
internal static string PluginUnpatchedAllRPCs(NetcodeValidator netcodeValidator)
{
return $"Plugin {netcodeValidator.PluginGuid} has unpatched all RPCs!";
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "NicholaScott.BepInEx.RuntimeNetcodeRPCValidator";
public const string PLUGIN_NAME = "RuntimeNetcodeRPCValidator";
public const string PLUGIN_VERSION = "0.2.5";
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}