using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Object;
using FishNet.Object;
using FishNet.Object.Delegating;
using FishNet.Serializing;
using FishNet.Transporting;
using FishUtilities.Attributes;
using FishUtilities.Helpers;
using FishUtilities.Network;
using FishUtilities.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("BepInEx")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("FishUtilities")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f0cc5570e7ffef25695b8901233090dca7ffce3f")]
[assembly: AssemblyProduct("FishUtilities")]
[assembly: AssemblyTitle("FishUtilities")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 FishUtilities
{
[BepInProcess("MageArena")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.d1gq.fish.utilities", "FishUtilities", "1.3.3")]
public class FUPlugin : BaseUnityPlugin
{
private const string MyGUID = "com.d1gq.fish.utilities";
internal const string PluginName = "FishUtilities";
private const string VersionString = "1.3.3";
internal static Harmony? Harmony;
private ManualLogSource? _log;
public static string modsync = "all";
internal static FUPlugin Instance { get; private set; }
internal static ManualLogSource Log => Instance._log;
private void Awake()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
_log = ((BaseUnityPlugin)this).Logger;
Instance = this;
Harmony = new Harmony("com.d1gq.fish.utilities");
Harmony.PatchAll();
Log.LogInfo((object)"FishUtilities v1.3.3 loaded!");
}
}
}
namespace FishUtilities.Patches
{
[HarmonyPatch(typeof(BootstrapNetworkManager))]
internal class BootstrapNetworkManagerPatch
{
private static Dictionary<Type, Dictionary<uint, Action<NetworkConnection, object[]>>> Cmds = new Dictionary<Type, Dictionary<uint, Action<NetworkConnection, object[]>>>();
private static Dictionary<Type, Dictionary<uint, Action<object[]>>> Rpcs = new Dictionary<Type, Dictionary<uint, Action<object[]>>>();
private static Dictionary<Type, Dictionary<uint, Action<object[]>>> TargetRpcs = new Dictionary<Type, Dictionary<uint, Action<object[]>>>();
private static bool hasLoaded;
private static BootstrapNetworkManager _BootstrapNetworkManager => BootstrapNetworkManager.instance;
[HarmonyPatch("Awake")]
[HarmonyPostfix]
private static void Awake_Postfix(BootstrapNetworkManager __instance)
{
NetworkInitialize(__instance);
}
private static void NetworkInitialize(BootstrapNetworkManager __instance)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected O, but got Unknown
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
((NetworkBehaviour)__instance).RegisterServerRpc(100u, new ServerRpcDelegate(HandleServerCmd));
((NetworkBehaviour)__instance).RegisterObserversRpc(101u, new ClientRpcDelegate(HandleClientRpc));
((NetworkBehaviour)__instance).RegisterTargetRpc(102u, new ClientRpcDelegate(HandleTargetRpc));
if (!hasLoaded)
{
hasLoaded = true;
((MonoBehaviour)FUPlugin.Instance).StartCoroutine(CoWaitForChainloader());
}
}
private static IEnumerator CoWaitForChainloader()
{
while (!Chainloader._loaded)
{
yield return null;
}
Cmds = FishCmdAttribute.GetStaticCmdFunctions();
Rpcs = FishRpcAttribute.GetStaticRpcFunctions();
TargetRpcs = FishTargetRpcAttribute.GetStaticTargetRpcFunctions();
}
internal static void SendCmd(Type type, uint cmdId, params object[] args)
{
if (!((NetworkBehaviour)_BootstrapNetworkManager).IsClientInitialized)
{
NetworkManagerExtensions.LogWarning(((NetworkBehaviour)_BootstrapNetworkManager).NetworkManager, "Cannot complete action because client is not active. This may also occur if the object is not yet initialized, has deinitialized, or if it does not contain a NetworkObject component.");
return;
}
PooledWriter val = WriterPool.Retrieve();
((Writer)val).Write<string>(type.FullName);
((Writer)val).Write<uint>(cmdId);
DataWriter dataWriter = new DataWriter();
foreach (object value in args)
{
dataWriter.Write(value);
}
dataWriter.WriteFromBuffer(val);
((NetworkBehaviour)_BootstrapNetworkManager).SendServerRpc(100u, val, (Channel)0, (DataOrderType)0);
}
private static void HandleServerCmd(PooledReader reader, Channel channel, NetworkConnection sender)
{
string type = ((Reader)reader).Read<string>();
uint cmdId = ((Reader)reader).Read<uint>();
DataWriter dataWriter = new DataWriter();
dataWriter.ReadToBuffer(reader);
HandleCmd(type, cmdId, sender, dataWriter.GetObjectBuffer());
}
private static void HandleCmd(string type, uint cmdId, NetworkConnection sender, object[] args)
{
string type2 = type;
if (Cmds.FirstOrDefault<KeyValuePair<Type, Dictionary<uint, Action<NetworkConnection, object[]>>>>((KeyValuePair<Type, Dictionary<uint, Action<NetworkConnection, object[]>>> kvp) => kvp.Key.FullName == type2).Value.TryGetValue(cmdId, out var value))
{
value(sender, args);
}
}
internal static void SendRpc(Type type, uint rpcId, params object[] args)
{
if (!((NetworkBehaviour)_BootstrapNetworkManager).IsClientInitialized)
{
NetworkManagerExtensions.LogWarning(((NetworkBehaviour)_BootstrapNetworkManager).NetworkManager, "Cannot complete action because client is not active. This may also occur if the object is not yet initialized, has deinitialized, or if it does not contain a NetworkObject component.");
return;
}
PooledWriter val = WriterPool.Retrieve();
((Writer)val).Write<string>(type.FullName);
((Writer)val).Write<uint>(rpcId);
DataWriter dataWriter = new DataWriter();
foreach (object value in args)
{
dataWriter.Write(value);
}
dataWriter.WriteFromBuffer(val);
((NetworkBehaviour)_BootstrapNetworkManager).SendObserversRpc(101u, val, (Channel)0, (DataOrderType)0, false, false, false);
}
private static void HandleClientRpc(PooledReader reader, Channel channel)
{
string type = ((Reader)reader).Read<string>();
uint rpcId = ((Reader)reader).Read<uint>();
DataWriter dataWriter = new DataWriter();
dataWriter.ReadToBuffer(reader);
HandleRpc(type, rpcId, dataWriter.GetObjectBuffer());
}
private static void HandleRpc(string type, uint rpcId, object[] args)
{
string type2 = type;
if (Rpcs.FirstOrDefault<KeyValuePair<Type, Dictionary<uint, Action<object[]>>>>((KeyValuePair<Type, Dictionary<uint, Action<object[]>>> kvp) => kvp.Key.FullName == type2).Value.TryGetValue(rpcId, out var value))
{
value(args);
}
}
internal static void SendTargetRpc(Type type, uint rpcId, NetworkConnection target, params object[] args)
{
if (!((NetworkBehaviour)_BootstrapNetworkManager).IsServerInitialized)
{
NetworkManagerExtensions.LogWarning(((NetworkBehaviour)_BootstrapNetworkManager).NetworkManager, "Cannot complete action because server is not active. This may also occur if the object is not yet initialized, has deinitialized, or if it does not contain a NetworkObject component.");
return;
}
PooledWriter val = WriterPool.Retrieve();
((Writer)val).Write<string>(type.FullName);
((Writer)val).Write<uint>(rpcId);
DataWriter dataWriter = new DataWriter();
foreach (object value in args)
{
dataWriter.Write(value);
}
dataWriter.WriteFromBuffer(val);
((NetworkBehaviour)_BootstrapNetworkManager).SendTargetRpc(102u, val, (Channel)0, (DataOrderType)0, target, false, true);
}
private static void HandleTargetRpc(PooledReader reader, Channel channel)
{
string type = ((Reader)reader).Read<string>();
uint rpcId = ((Reader)reader).Read<uint>();
NetworkConnection connection = ((NetworkBehaviour)_BootstrapNetworkManager).ClientManager.Connection;
DataWriter dataWriter = new DataWriter();
dataWriter.ReadToBuffer(reader);
HandleTargetRpc(type, rpcId, connection, dataWriter.GetObjectBuffer());
}
private static void HandleTargetRpc(string type, uint rpcId, NetworkConnection target, object[] args)
{
string type2 = type;
KeyValuePair<Type, Dictionary<uint, Action<object[]>>> keyValuePair = TargetRpcs.FirstOrDefault<KeyValuePair<Type, Dictionary<uint, Action<object[]>>>>((KeyValuePair<Type, Dictionary<uint, Action<object[]>>> kvp) => kvp.Key.FullName == type2);
if (keyValuePair.Value != null && keyValuePair.Value.TryGetValue(rpcId, out var value))
{
object[] array = new object[args.Length + 1];
array[0] = target;
Array.Copy(args, 0, array, 1, args.Length);
value(array);
}
}
}
}
namespace FishUtilities.Network
{
public abstract class CustomNetworkBehaviour : NetworkBehaviour
{
private bool _netInit;
protected virtual void Awake()
{
NetworkInitialize();
}
private void NetworkInitialize()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
if (!_netInit)
{
_netInit = true;
((NetworkBehaviour)this).RegisterServerRpc(0u, new ServerRpcDelegate(HandleServerCmd));
((NetworkBehaviour)this).RegisterObserversRpc(1u, new ClientRpcDelegate(HandleClientRpc));
}
}
protected void SendCmd(uint cmdId, params object[] args)
{
if (!((NetworkBehaviour)this).IsClientInitialized)
{
NetworkManagerExtensions.LogWarning(((NetworkBehaviour)this).NetworkManager, "Cannot complete action because client is not active. This may also occur if the object is not yet initialized, has deinitialized, or if it does not contain a NetworkObject component.");
return;
}
PooledWriter val = WriterPool.Retrieve();
((Writer)val).Write<uint>(cmdId);
DataWriter dataWriter = new DataWriter();
foreach (object value in args)
{
dataWriter.Write(value);
}
dataWriter.WriteFromBuffer(val);
((NetworkBehaviour)this).SendServerRpc(0u, val, (Channel)0, (DataOrderType)0);
}
protected virtual void HandleCmd(uint cmdId, NetworkConnection sender, object[] args)
{
}
private void HandleServerCmd(PooledReader reader, Channel channel, NetworkConnection sender)
{
uint cmdId = ((Reader)reader).Read<uint>();
DataWriter dataWriter = new DataWriter();
dataWriter.ReadToBuffer(reader);
HandleCmd(cmdId, sender, dataWriter.GetObjectBuffer());
}
protected void SendRpc(uint rpcId, params object[] args)
{
if (!((NetworkBehaviour)this).IsClientInitialized)
{
NetworkManagerExtensions.LogWarning(((NetworkBehaviour)this).NetworkManager, "Cannot complete action because client is not active. This may also occur if the object is not yet initialized, has deinitialized, or if it does not contain a NetworkObject component.");
return;
}
PooledWriter val = WriterPool.Retrieve();
((Writer)val).Write<uint>(rpcId);
DataWriter dataWriter = new DataWriter();
foreach (object value in args)
{
dataWriter.Write(value);
}
dataWriter.WriteFromBuffer(val);
((NetworkBehaviour)this).SendObserversRpc(1u, val, (Channel)0, (DataOrderType)0, false, false, false);
}
protected virtual void HandleRpc(uint rpcId, object[] args)
{
}
private void HandleClientRpc(PooledReader reader, Channel channel)
{
uint rpcId = ((Reader)reader).Read<uint>();
DataWriter dataWriter = new DataWriter();
dataWriter.ReadToBuffer(reader);
HandleRpc(rpcId, dataWriter.GetObjectBuffer());
}
}
public class DataWriter : IDisposable
{
private readonly List<(Type type, object value)> _dataBuffer = new List<(Type, object)>();
public void Write<T>(T value)
{
if (value != null)
{
_dataBuffer.Add((typeof(T), value));
}
}
public void Write(object value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
_dataBuffer.Add((value.GetType(), value));
}
public void WriteFromBuffer(PooledWriter writer)
{
((Writer)writer).Write<byte>((byte)_dataBuffer.Count);
foreach (var (type, value) in _dataBuffer)
{
((Writer)writer).Write<string>(type.AssemblyQualifiedName);
writer.WriteFast(type, value);
}
}
public void ReadToBuffer(PooledReader reader)
{
ClearBuffer();
byte b = ((Reader)reader).Read<byte>();
for (int i = 0; i < b; i++)
{
string text = ((Reader)reader).ReadString();
Type type = Type.GetType(text) ?? throw new InvalidOperationException("Type not found: " + text);
object obj = reader.ReadFast(type);
_dataBuffer.Add((obj.GetType(), obj));
}
}
public object[] GetObjectBuffer()
{
object[] array = new object[_dataBuffer.Count];
for (int i = 0; i < _dataBuffer.Count; i++)
{
array[i] = _dataBuffer[i].value;
}
return array;
}
public void ClearBuffer()
{
_dataBuffer.Clear();
}
public void Dispose()
{
ClearBuffer();
GC.SuppressFinalize(this);
}
}
}
namespace FishUtilities.Managers
{
public static class FishManager
{
private static ushort? prefabIdStart;
private static readonly List<(string hash, NetworkObject net)> netObjs = new List<(string, NetworkObject)>();
private static readonly List<string> registered = new List<string>();
[Obsolete("Directly call method instead!")]
public static void SendRpc<T>(string methodName, params object[] args)
{
MethodInfo method = GetMethod<T>(methodName);
FishRpcAttribute rpcAttribute = GetRpcAttribute(method);
ValidateArguments(method, args);
BootstrapNetworkManagerPatch.SendRpc(typeof(T), rpcAttribute.Id, args);
}
[Obsolete("Directly call method instead!")]
public static void SendCmd<T>(string methodName, params object[] args)
{
MethodInfo method = GetMethod<T>(methodName);
FishCmdAttribute cmdAttribute = GetCmdAttribute(method);
ValidateArguments(method, args);
BootstrapNetworkManagerPatch.SendCmd(typeof(T), cmdAttribute.Id, args);
}
private static MethodInfo GetMethod<T>(string methodName)
{
MethodInfo? method = typeof(T).GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (method == null)
{
throw new ArgumentException("Method " + methodName + " not found in type " + typeof(T).Name);
}
return method;
}
private static FishRpcAttribute GetRpcAttribute(MethodInfo method)
{
return method.GetCustomAttribute<FishRpcAttribute>() ?? throw new InvalidOperationException("Method " + method.Name + " is not decorated with [FishRpcAttribute]");
}
private static FishCmdAttribute GetCmdAttribute(MethodInfo method)
{
return method.GetCustomAttribute<FishCmdAttribute>() ?? throw new InvalidOperationException("Method " + method.Name + " is not decorated with [FishCmdAttribute]");
}
private static void ValidateArguments(MethodInfo method, object[] providedArgs)
{
ParameterInfo[] parameters = method.GetParameters();
int num = providedArgs.Length;
int num2 = parameters.Length;
if (parameters.Length != 0 && parameters[0].ParameterType == typeof(NetworkConnection))
{
num2 = parameters.Length - 1;
}
if (num != num2)
{
throw new ArgumentException("Argument count mismatch for method " + method.Name + ". " + $"Expected {num2}, got {num}");
}
int num3 = ((parameters.Length != 0 && parameters[0].ParameterType == typeof(NetworkConnection)) ? 1 : 0);
for (int i = 0; i < num; i++)
{
Type parameterType = parameters[i + num3].ParameterType;
Type type = providedArgs[i]?.GetType();
if (providedArgs[i] != null && !parameterType.IsAssignableFrom(type))
{
throw new ArgumentException("Argument type mismatch for parameter " + parameters[i + num3].Name + " in method " + method.Name + ". Expected " + parameterType.Name + ", got " + (type?.Name ?? "null"));
}
}
}
public static T? SpawnNetworkObject<T>(this T mono, Vector3? position = null, Vector3? scale = null, Quaternion? rotation = null) where T : MonoBehaviour
{
GameObject? obj = ((Component)(object)mono).gameObject.SpawnNetworkObject(position, scale, rotation);
if (obj == null)
{
return default(T);
}
return obj.GetComponent<T>();
}
public static GameObject? SpawnNetworkObject(this GameObject gameObject, Vector3? position = null, Vector3? scale = null, Quaternion? rotation = null)
{
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
NetworkObject component = gameObject.GetComponent<NetworkObject>();
if ((Object)(object)component == (Object)null)
{
FUPlugin.Log.LogError((object)"Failed to spawn NetworkObject: GameObjects must have the NetworkObject component to be spawnable!");
return null;
}
if (component.PrefabId == ushort.MaxValue)
{
FUPlugin.Log.LogError((object)"Failed to spawn NetworkObject: NetworkObject has an unset prefab id!");
return null;
}
NetworkManager val = NetworkManager.Instances.FirstOrDefault();
if ((Object)(object)val == (Object)null)
{
FUPlugin.Log.LogError((object)$"Failed to spawn NetworkObject({component.PrefabId}): NetworkManager is null!");
return null;
}
if (!val.IsHostStarted)
{
FUPlugin.Log.LogError((object)$"Failed to spawn NetworkObject({component.PrefabId}): NetworkObjects can only be spawned as host.");
return null;
}
if (position.HasValue)
{
gameObject.transform.position = position.Value;
}
if (scale.HasValue)
{
gameObject.transform.localScale = scale.Value;
}
if (rotation.HasValue)
{
gameObject.transform.rotation = rotation.Value;
}
val.ServerManager.Spawn(gameObject, (NetworkConnection)null, default(Scene));
return gameObject;
}
public static void RegisterNetworkObjectPrefab(this BaseUnityPlugin plugin, MonoBehaviour mono, string uniqueIdentifier = "", bool dontDestroy = true)
{
string text = ((uniqueIdentifier.Length > 0) ? (" + " + uniqueIdentifier) : "");
if ((Object)(object)mono == (Object)null)
{
FUPlugin.Log.LogError((object)("Failed to register (" + ((object)mono)?.GetType().FullName + text + ") Network Object from $" + plugin.Info.Metadata.GUID + ": MonoBehavior cannot be null!"));
return;
}
string text2 = FishUtils.GenerateHash(plugin.GetUniqueHash() + "|" + ((object)mono).GetType().FullName + "|" + uniqueIdentifier);
if (registered.Contains(text2))
{
FUPlugin.Log.LogError((object)("Failed to register (" + ((object)mono)?.GetType().FullName + text + ") Network Object from $" + plugin.Info.Metadata.GUID + ": MonoBehavior has already been registered under " + text2));
return;
}
if (dontDestroy)
{
Object.DontDestroyOnLoad((Object)(object)((Component)mono).gameObject);
((Component)mono).gameObject.SetActive(false);
}
SynchronizeNetworkObjectPrefab(((Component)mono).gameObject, text2);
FUPlugin.Log.LogInfo((object)("Successfully registered (" + ((object)mono)?.GetType().FullName + text + ") Network Object from " + plugin.Info.Metadata.GUID + " under " + text2));
}
internal static void SynchronizeNetworkObjectPrefab(GameObject obj, string hash)
{
GameObject obj2 = obj;
string hash2 = hash;
NetworkObject val = default(NetworkObject);
if (obj2.TryGetComponent<NetworkObject>(ref val))
{
Object.DestroyImmediate((Object)(object)val);
}
((MonoBehaviour)FUPlugin.Instance).StartCoroutine(CoWaitForNetwork());
IEnumerator CoWaitForNetwork()
{
while (NetworkManager.Instances.Count == 0)
{
yield return null;
}
if (!((Object)(object)obj2 == (Object)null))
{
NetworkObject val2 = obj2.gameObject.AddComponent<NetworkObject>();
val2.NetworkBehaviours = new List<NetworkBehaviour>();
NetworkManager val3 = NetworkManager.Instances.First();
val3.SpawnablePrefabs.AddObject(val2, true);
prefabIdStart.GetValueOrDefault();
if (!prefabIdStart.HasValue)
{
ushort prefabId = val2.PrefabId;
prefabIdStart = prefabId;
}
ushort? num = prefabIdStart;
netObjs.Add((hash2, val2));
registered.Add(hash2);
foreach (var item in netObjs.OrderBy<(string, NetworkObject), string>(((string hash, NetworkObject net) i) => i.hash))
{
typeof(NetworkObject).GetProperty("PrefabId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(item.Item2, num);
num++;
}
List<NetworkObject> list = ((SinglePrefabObjects)(DefaultPrefabObjects)val3.SpawnablePrefabs).Prefabs.OrderBy(delegate(NetworkObject prefab)
{
NetworkObject component = ((Component)prefab).GetComponent<NetworkObject>();
return (!((Object)(object)component != (Object)null)) ? int.MaxValue : component.PrefabId;
}).ToList();
DefaultPrefabObjects val4 = ScriptableObject.CreateInstance<DefaultPrefabObjects>();
((PrefabObjects)val4).AddObjects(list, false);
val3.SpawnablePrefabs = (PrefabObjects)(object)val4;
}
}
}
}
}
namespace FishUtilities.Helpers
{
public static class FishUtils
{
private static readonly Dictionary<Type, Func<PooledReader, object>> _readers = new Dictionary<Type, Func<PooledReader, object>>
{
{
typeof(bool),
(PooledReader reader) => ((Reader)reader).ReadBoolean()
},
{
typeof(char),
(PooledReader reader) => ((Reader)reader).ReadChar()
},
{
typeof(short),
(PooledReader reader) => ((Reader)reader).ReadInt16()
},
{
typeof(ushort),
(PooledReader reader) => ((Reader)reader).ReadUInt16()
},
{
typeof(int),
(PooledReader reader) => ((Reader)reader).ReadInt32()
},
{
typeof(uint),
(PooledReader reader) => ((Reader)reader).ReadUInt32()
},
{
typeof(long),
(PooledReader reader) => ((Reader)reader).ReadInt64()
},
{
typeof(ulong),
(PooledReader reader) => ((Reader)reader).ReadUInt64()
},
{
typeof(float),
(PooledReader reader) => ((Reader)reader).ReadSingle()
},
{
typeof(double),
(PooledReader reader) => ((Reader)reader).ReadDouble()
},
{
typeof(decimal),
(PooledReader reader) => ((Reader)reader).ReadDecimal()
},
{
typeof(string),
(PooledReader reader) => ((Reader)reader).ReadString()
},
{
typeof(Vector2),
(PooledReader reader) => ((Reader)reader).ReadVector2()
},
{
typeof(Vector3),
(PooledReader reader) => ((Reader)reader).ReadVector3()
},
{
typeof(Vector4),
(PooledReader reader) => ((Reader)reader).ReadVector4()
},
{
typeof(Vector2Int),
(PooledReader reader) => ((Reader)reader).ReadVector2Int()
},
{
typeof(Vector3Int),
(PooledReader reader) => ((Reader)reader).ReadVector3Int()
},
{
typeof(Color),
(PooledReader reader) => ((Reader)reader).ReadColor()
},
{
typeof(Color32),
(PooledReader reader) => ((Reader)reader).ReadColor32()
},
{
typeof(Rect),
(PooledReader reader) => ((Reader)reader).ReadRect()
},
{
typeof(Plane),
(PooledReader reader) => ((Reader)reader).ReadPlane()
},
{
typeof(Ray),
(PooledReader reader) => ((Reader)reader).ReadRay()
},
{
typeof(Ray2D),
(PooledReader reader) => ((Reader)reader).ReadRay2D()
},
{
typeof(Matrix4x4),
(PooledReader reader) => ((Reader)reader).ReadMatrix4x4()
},
{
typeof(DateTime),
(PooledReader reader) => ((Reader)reader).ReadDateTime()
},
{
typeof(Guid),
(PooledReader reader) => ((Reader)reader).ReadGuid()
},
{
typeof(NetworkObject),
(PooledReader reader) => ((Reader)reader).ReadNetworkObject()
},
{
typeof(NetworkBehaviour),
(PooledReader reader) => ((Reader)reader).ReadNetworkBehaviour()
},
{
typeof(NetworkConnection),
(PooledReader reader) => ((Reader)reader).ReadNetworkConnection()
},
{
typeof(Channel),
(PooledReader reader) => ((Reader)reader).ReadChannel()
},
{
typeof(GameObject),
(PooledReader reader) => ((Reader)reader).ReadGameObject()
}
};
private static readonly Dictionary<Type, Action<PooledWriter, object>> _writers = new Dictionary<Type, Action<PooledWriter, object>>
{
{
typeof(bool),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteBoolean((bool)value);
}
},
{
typeof(char),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteChar((char)value);
}
},
{
typeof(short),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteInt16((short)value);
}
},
{
typeof(ushort),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteUInt16((ushort)value);
}
},
{
typeof(int),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteInt32((int)value);
}
},
{
typeof(uint),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteUInt32((uint)value);
}
},
{
typeof(long),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteInt64((long)value);
}
},
{
typeof(ulong),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteUInt64((ulong)value);
}
},
{
typeof(float),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteSingle((float)value);
}
},
{
typeof(double),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteDouble((double)value);
}
},
{
typeof(decimal),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteDecimal((decimal)value);
}
},
{
typeof(string),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteString((string)value);
}
},
{
typeof(Vector2),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteVector2((Vector2)value);
}
},
{
typeof(Vector3),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteVector3((Vector3)value);
}
},
{
typeof(Vector4),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteVector4((Vector4)value);
}
},
{
typeof(Vector2Int),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteVector2Int((Vector2Int)value);
}
},
{
typeof(Vector3Int),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteVector3Int((Vector3Int)value);
}
},
{
typeof(Color),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteColor((Color)value);
}
},
{
typeof(Color32),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteColor32((Color32)value);
}
},
{
typeof(Rect),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteRect((Rect)value);
}
},
{
typeof(Plane),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WritePlane((Plane)value);
}
},
{
typeof(Ray),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteRay((Ray)value);
}
},
{
typeof(Ray2D),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteRay2D((Ray2D)value);
}
},
{
typeof(Matrix4x4),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteMatrix4x4((Matrix4x4)value);
}
},
{
typeof(DateTime),
delegate(PooledWriter writer, object value)
{
((Writer)writer).WriteDateTime((DateTime)value);
}
},
{
typeof(NetworkObject),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
((Writer)writer).WriteNetworkObject((NetworkObject)value);
}
},
{
typeof(NetworkBehaviour),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
((Writer)writer).WriteNetworkBehaviour((NetworkBehaviour)value);
}
},
{
typeof(NetworkConnection),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
((Writer)writer).WriteNetworkConnection((NetworkConnection)value);
}
},
{
typeof(Channel),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
((Writer)writer).WriteChannel((Channel)value);
}
},
{
typeof(GameObject),
delegate(PooledWriter writer, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
((Writer)writer).WriteGameObject((GameObject)value);
}
}
};
public static object ReadFast(this PooledReader reader, Type type)
{
if (_readers.TryGetValue(type, out Func<PooledReader, object> value))
{
return value(reader);
}
throw new NotSupportedException("Type " + type.Name + " is not supported for fast reading");
}
public static void WriteFast(this PooledWriter writer, Type type, object value)
{
if (_writers.TryGetValue(type, out Action<PooledWriter, object> value2))
{
value2(writer, value);
return;
}
throw new NotSupportedException("Type " + type.Name + " is not supported for fast writing");
}
internal static string GenerateHash(string input)
{
using SHA256 sHA = SHA256.Create();
return BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(input))).Trim();
}
internal static string GetUniqueHash(this BaseUnityPlugin baseUnity)
{
return GenerateHash(baseUnity.Info.Metadata.GUID + "|" + baseUnity.Info.Metadata.Name);
}
}
}
namespace FishUtilities.Attributes
{
[AttributeUsage(AttributeTargets.Method)]
public class FishCmdAttribute : Attribute
{
private static class InternalCallContext
{
[ThreadStatic]
public static bool IsInternalCall;
}
private static readonly Dictionary<MethodInfo, (Type, uint)> _patchedMethods = new Dictionary<MethodInfo, (Type, uint)>();
internal uint Id { get; set; }
public FishCmdAttribute()
{
}
[Obsolete("Ids are automatically assigned now. Use parameterless constructor instead.", true)]
public FishCmdAttribute(uint id)
{
}
internal static Dictionary<Type, Dictionary<uint, Action<NetworkConnection, object[]>>> GetStaticCmdFunctions()
{
Dictionary<Type, Dictionary<uint, Action<NetworkConnection, object[]>>> dictionary = new Dictionary<Type, Dictionary<uint, Action<NetworkConnection, object[]>>>();
foreach (Assembly item in from pi in Chainloader.PluginInfos.Values
select ((object)pi.Instance).GetType().Assembly into a
orderby a.FullName
select a)
{
try
{
foreach (Type item2 in from type in item.GetTypes()
orderby type.FullName
select type)
{
MethodInfo[] methods = item2.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
uint num = 0u;
foreach (MethodInfo item3 in methods.OrderBy((MethodInfo met) => met.Name))
{
FishCmdAttribute customAttribute = item3.GetCustomAttribute<FishCmdAttribute>();
if (customAttribute != null)
{
customAttribute.Id = num;
num++;
if (!dictionary.TryGetValue(item2, out var value))
{
value = (dictionary[item2] = new Dictionary<uint, Action<NetworkConnection, object[]>>());
}
Action<NetworkConnection, object[]> value2 = CreateCmdAction(item3);
value[customAttribute.Id] = value2;
PatchMethod(item3, item2, customAttribute.Id);
}
}
}
}
catch (ReflectionTypeLoadException)
{
}
}
return dictionary;
}
private static Action<NetworkConnection, object[]> CreateCmdAction(MethodInfo method)
{
MethodInfo method2 = method;
return delegate(NetworkConnection connection, object[] parameters)
{
InternalCallContext.IsInternalCall = true;
ParameterInfo[] parameters2 = method2.GetParameters();
object[] array;
if (parameters2.Length != 0 && parameters2[0].ParameterType == typeof(NetworkConnection))
{
array = new object[parameters.Length + 1];
array[0] = connection;
Array.Copy(parameters, 0, array, 1, parameters.Length);
}
else
{
array = parameters;
}
method2.Invoke(null, array);
};
}
private static void PatchMethod(MethodInfo method, Type declaringType, uint cmdId)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
_patchedMethods[method] = (declaringType, cmdId);
Harmony? harmony = FUPlugin.Harmony;
if (harmony != null)
{
harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(FishCmdAttribute).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
[HarmonyPrefix]
private static bool Prefix(MethodBase __originalMethod, object[] __args)
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
if (__originalMethod is MethodInfo methodInfo && _patchedMethods.TryGetValue(methodInfo, out (Type, uint) value))
{
if (InternalCallContext.IsInternalCall)
{
InternalCallContext.IsInternalCall = false;
return true;
}
(Type, uint) tuple = value;
Type item = tuple.Item1;
uint item2 = tuple.Item2;
object[] args = __args;
ParameterInfo[] parameters = methodInfo.GetParameters();
if (__args.Length != 0 && parameters.Length != 0 && parameters[0].ParameterType == typeof(NetworkConnection))
{
args = ((__args.Length > 1) ? __args[Range.StartAt(Index.op_Implicit(1))] : Array.Empty<object>());
}
BootstrapNetworkManagerPatch.SendCmd(item, item2, args);
return false;
}
return true;
}
}
[AttributeUsage(AttributeTargets.Method)]
public class FishRpcAttribute : Attribute
{
private static class InternalCallContext
{
[ThreadStatic]
public static bool IsInternalCall;
}
private static readonly Dictionary<MethodInfo, (Type, uint)> _patchedMethods = new Dictionary<MethodInfo, (Type, uint)>();
internal uint Id { get; set; }
public FishRpcAttribute()
{
}
[Obsolete("Ids are automatically assigned now. Use parameterless constructor instead.", true)]
public FishRpcAttribute(uint id)
{
}
internal static Dictionary<Type, Dictionary<uint, Action<object[]>>> GetStaticRpcFunctions()
{
Dictionary<Type, Dictionary<uint, Action<object[]>>> dictionary = new Dictionary<Type, Dictionary<uint, Action<object[]>>>();
foreach (Assembly item in from pi in Chainloader.PluginInfos.Values
select ((object)pi.Instance).GetType().Assembly into a
orderby a.FullName
select a)
{
try
{
foreach (Type item2 in from type in item.GetTypes()
orderby type.FullName
select type)
{
MethodInfo[] methods = item2.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
uint num = 0u;
foreach (MethodInfo item3 in methods.OrderBy((MethodInfo met) => met.Name))
{
FishRpcAttribute customAttribute = item3.GetCustomAttribute<FishRpcAttribute>();
if (customAttribute != null)
{
customAttribute.Id = num;
num++;
if (!dictionary.TryGetValue(item2, out var value))
{
value = (dictionary[item2] = new Dictionary<uint, Action<object[]>>());
}
Action<object[]> value2 = CreateRpcAction(item3);
value[customAttribute.Id] = value2;
PatchMethod(item3, item2, customAttribute.Id);
}
}
}
}
catch (ReflectionTypeLoadException)
{
}
}
return dictionary;
}
private static Action<object[]> CreateRpcAction(MethodInfo method)
{
MethodInfo method2 = method;
return delegate(object[] parameters)
{
InternalCallContext.IsInternalCall = true;
method2.Invoke(null, parameters);
};
}
private static void PatchMethod(MethodInfo method, Type declaringType, uint rpcId)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
_patchedMethods[method] = (declaringType, rpcId);
Harmony? harmony = FUPlugin.Harmony;
if (harmony != null)
{
harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(FishRpcAttribute).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
[HarmonyPrefix]
private static bool Prefix(MethodBase __originalMethod, object[] __args)
{
if (__originalMethod is MethodInfo key && _patchedMethods.TryGetValue(key, out (Type, uint) value))
{
if (InternalCallContext.IsInternalCall)
{
InternalCallContext.IsInternalCall = false;
return true;
}
var (type, rpcId) = value;
BootstrapNetworkManagerPatch.SendRpc(type, rpcId, __args);
return false;
}
return true;
}
}
[AttributeUsage(AttributeTargets.Method)]
public class FishTargetRpcAttribute : Attribute
{
private static class InternalCallContext
{
[ThreadStatic]
public static bool IsInternalCall;
}
private static readonly Dictionary<MethodInfo, (Type, uint)> _patchedMethods = new Dictionary<MethodInfo, (Type, uint)>();
internal uint Id { get; set; }
internal static Dictionary<Type, Dictionary<uint, Action<object[]>>> GetStaticTargetRpcFunctions()
{
Dictionary<Type, Dictionary<uint, Action<object[]>>> dictionary = new Dictionary<Type, Dictionary<uint, Action<object[]>>>();
foreach (Assembly item in from pi in Chainloader.PluginInfos.Values
select ((object)pi.Instance).GetType().Assembly into a
orderby a.FullName
select a)
{
try
{
foreach (Type item2 in from type in item.GetTypes()
orderby type.FullName
select type)
{
MethodInfo[] methods = item2.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
uint num = 0u;
foreach (MethodInfo item3 in methods.OrderBy((MethodInfo met) => met.Name))
{
FishTargetRpcAttribute customAttribute = item3.GetCustomAttribute<FishTargetRpcAttribute>();
if (customAttribute != null)
{
ParameterInfo[] parameters = item3.GetParameters();
if (parameters.Length == 0 || parameters[0].ParameterType != typeof(NetworkConnection))
{
throw new InvalidOperationException("Target RPC method " + item3.Name + " in " + item2.FullName + " must have NetworkConnection as the first parameter");
}
customAttribute.Id = num;
num++;
if (!dictionary.TryGetValue(item2, out var value))
{
value = (dictionary[item2] = new Dictionary<uint, Action<object[]>>());
}
Action<object[]> value2 = CreateTargetRpcAction(item3);
value[customAttribute.Id] = value2;
PatchMethod(item3, item2, customAttribute.Id);
}
}
}
}
catch (ReflectionTypeLoadException)
{
}
}
return dictionary;
}
private static Action<object[]> CreateTargetRpcAction(MethodInfo method)
{
MethodInfo method2 = method;
return delegate(object[] parameters)
{
InternalCallContext.IsInternalCall = true;
method2.Invoke(null, parameters);
};
}
private static void PatchMethod(MethodInfo method, Type declaringType, uint rpcId)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
_patchedMethods[method] = (declaringType, rpcId);
Harmony? harmony = FUPlugin.Harmony;
if (harmony != null)
{
harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(FishTargetRpcAttribute).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
[HarmonyPrefix]
private static bool Prefix(MethodBase __originalMethod, object[] __args)
{
if (__originalMethod is MethodInfo key && _patchedMethods.TryGetValue(key, out (Type, uint) value))
{
if (InternalCallContext.IsInternalCall)
{
InternalCallContext.IsInternalCall = false;
return true;
}
var (type, rpcId) = value;
if (__args.Length != 0)
{
object obj = __args[0];
NetworkConnection val = (NetworkConnection)((obj is NetworkConnection) ? obj : null);
if (val != null)
{
object[] args = __args.Skip(1).ToArray();
BootstrapNetworkManagerPatch.SendTargetRpc(type, rpcId, val, args);
}
}
return false;
}
return true;
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}