using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks;
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("Ashley.MeshSplitter")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("com.rlabrecque.steamworks.net")]
[assembly: IgnoresAccessChecksTo("Discord")]
[assembly: IgnoresAccessChecksTo("HBAO.Demo.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("HBAO.Runtime")]
[assembly: IgnoresAccessChecksTo("HBAO.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("MeshSplit")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonChat")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.API")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")]
[assembly: IgnoresAccessChecksTo("pworld")]
[assembly: IgnoresAccessChecksTo("sc.posteffects.runtime")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.UnityLocalization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Utilities")]
[assembly: IgnoresAccessChecksTo("Tayx.Graphy")]
[assembly: IgnoresAccessChecksTo("Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.013")]
[assembly: IgnoresAccessChecksTo("Unity.Localization")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.PlayableGraphVisualizer")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipeline.Universal.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Shaders")]
[assembly: IgnoresAccessChecksTo("Unity.ResourceManager")]
[assembly: IgnoresAccessChecksTo("Unity.ScriptableBuildPipeline")]
[assembly: IgnoresAccessChecksTo("Unity.Splines")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("Zorro.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Zorro.PhotonUtility")]
[assembly: IgnoresAccessChecksTo("Zorro.Recorder")]
[assembly: IgnoresAccessChecksTo("Zorro.Settings.Runtime")]
[assembly: IgnoresAccessChecksTo("Zorro.UI.Runtime")]
[assembly: AssemblyCompany("RugbugRedfern")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.14.0")]
[assembly: AssemblyInformationalVersion("1.0.14+2efbc5cb2bb4d03a71c503581dbd17a763b97873")]
[assembly: AssemblyProduct("Mycelium Networking")]
[assembly: AssemblyTitle("MyceliumNetworkingForCW")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/RugbugRedfern/Mycelium-Networking-For-Content-Warning")]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace MyceliumNetworking
{
[AttributeUsage(AttributeTargets.Method)]
public class CustomRPCAttribute : Attribute
{
}
public class Message : IDisposable
{
private const int MYCELIUM_VERSION = 1;
public byte MyceliumVersion;
public int Mask;
public uint ModID;
public string MethodName;
private List<byte> buffer;
private byte[] readableBuffer;
private int readPos;
private Dictionary<Type, Action<Message, object>> WriteCasters = new Dictionary<Type, Action<Message, object>>
{
{
typeof(byte),
delegate(Message msg, object value)
{
msg.WriteByte((byte)value);
}
},
{
typeof(byte[]),
delegate(Message msg, object value)
{
msg.WriteBytes((byte[])value);
}
},
{
typeof(bool),
delegate(Message msg, object value)
{
msg.WriteBool((bool)value);
}
},
{
typeof(bool[]),
delegate(Message msg, object value)
{
msg.WriteBools((bool[])value);
}
},
{
typeof(int),
delegate(Message msg, object value)
{
msg.WriteInt((int)value);
}
},
{
typeof(uint),
delegate(Message msg, object value)
{
msg.WriteUInt((uint)value);
}
},
{
typeof(short),
delegate(Message msg, object value)
{
msg.WriteShort((short)value);
}
},
{
typeof(ushort),
delegate(Message msg, object value)
{
msg.WriteUShort((ushort)value);
}
},
{
typeof(long),
delegate(Message msg, object value)
{
msg.WriteLong((long)value);
}
},
{
typeof(ulong),
delegate(Message msg, object value)
{
msg.WriteULong((ulong)value);
}
},
{
typeof(float),
delegate(Message msg, object value)
{
msg.WriteFloat((float)value);
}
},
{
typeof(string),
delegate(Message msg, object value)
{
msg.WriteString((string)value);
}
},
{
typeof(Vector3),
delegate(Message msg, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
msg.WriteVector3((Vector3)value);
}
},
{
typeof(Quaternion),
delegate(Message msg, object value)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
msg.WriteQuaternion((Quaternion)value);
}
},
{
typeof(CSteamID),
delegate(Message msg, object value)
{
msg.WriteULong(((CSteamID)value).m_SteamID);
}
}
};
private Dictionary<Type, Func<Message, object>> ReadCasters = new Dictionary<Type, Func<Message, object>>
{
{
typeof(byte),
(Message msg) => msg.ReadByte()
},
{
typeof(byte[]),
(Message msg) => msg.ReadBytes()
},
{
typeof(bool),
(Message msg) => msg.ReadBool()
},
{
typeof(bool[]),
(Message msg) => msg.ReadBools()
},
{
typeof(int),
(Message msg) => msg.ReadInt()
},
{
typeof(uint),
(Message msg) => msg.ReadUInt()
},
{
typeof(short),
(Message msg) => msg.ReadShort()
},
{
typeof(ushort),
(Message msg) => msg.ReadUShort()
},
{
typeof(long),
(Message msg) => msg.ReadLong()
},
{
typeof(ulong),
(Message msg) => msg.ReadULong()
},
{
typeof(float),
(Message msg) => msg.ReadFloat()
},
{
typeof(string),
(Message msg) => msg.ReadString()
},
{
typeof(Vector3),
(Message msg) => msg.ReadVector3()
},
{
typeof(Quaternion),
(Message msg) => msg.ReadQuaternion()
},
{
typeof(CSteamID),
(Message msg) => (CSteamID)msg.ReadULong()
}
};
private bool disposed;
public static int MaxSize { get; private set; } = 524288;
public string GetDestination()
{
return $"{ModID}: {MethodName}";
}
public Message(uint modID, string methodName, int mask)
{
buffer = new List<byte>();
readPos = 0;
MyceliumVersion = 1;
ModID = modID;
MethodName = methodName;
Mask = mask;
WriteByte(MyceliumVersion);
WriteUInt(ModID);
WriteString(MethodName);
WriteInt(Mask);
}
public Message(byte[] data)
{
buffer = new List<byte>();
readPos = 0;
SetBytes(data);
MyceliumVersion = ReadByte();
ModID = ReadUInt();
MethodName = ReadString();
Mask = ReadInt();
}
public void SetBytes(byte[] data)
{
buffer.AddRange(data);
readableBuffer = buffer.ToArray();
}
public void WriteLength()
{
buffer.InsertRange(0, BitConverter.GetBytes(buffer.Count));
}
public byte[] ToArray()
{
readableBuffer = buffer.ToArray();
return readableBuffer;
}
public int Length()
{
return buffer.Count;
}
public int UnreadLength()
{
return Length() - readPos;
}
public void Reset(bool shouldReset = true)
{
if (shouldReset)
{
buffer.Clear();
readableBuffer = null;
readPos = 0;
}
else
{
readPos -= 4;
}
}
public Message WriteByte(byte value)
{
buffer.Add(value);
return this;
}
public Message WriteBytes(byte[] value)
{
WriteInt(value.Length);
buffer.AddRange(value);
return this;
}
public Message WriteBools(bool[] value)
{
WriteInt(value.Length);
byte[] array = new byte[value.Length];
for (int i = 0; i < array.Length; i++)
{
array[i] = (value[i] ? ((byte)1) : ((byte)0));
}
buffer.AddRange(array);
return this;
}
public Message WriteShort(short value)
{
buffer.AddRange(BitConverter.GetBytes(value));
return this;
}
public Message WriteUShort(ushort value)
{
buffer.AddRange(BitConverter.GetBytes(value));
return this;
}
public Message WriteInt(int value)
{
buffer.AddRange(BitConverter.GetBytes(value));
return this;
}
public Message WriteUInt(uint value)
{
buffer.AddRange(BitConverter.GetBytes(value));
return this;
}
public Message InsertInt(int value)
{
buffer.InsertRange(1, BitConverter.GetBytes(value));
return this;
}
public Message WriteLong(long value)
{
buffer.AddRange(BitConverter.GetBytes(value));
return this;
}
public Message WriteULong(ulong value)
{
buffer.AddRange(BitConverter.GetBytes(value));
return this;
}
public Message WriteFloat(float value)
{
buffer.AddRange(BitConverter.GetBytes(value));
return this;
}
public Message WriteBool(bool value)
{
buffer.AddRange(BitConverter.GetBytes(value));
return this;
}
public Message WriteString(string value)
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
WriteInt(bytes.Length);
buffer.AddRange(bytes);
return this;
}
public Message WriteVector3(Vector3 value)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
WriteFloat(value.x);
WriteFloat(value.y);
WriteFloat(value.z);
return this;
}
public Message WriteQuaternion(Quaternion value)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
WriteFloat(value.x);
WriteFloat(value.y);
WriteFloat(value.z);
WriteFloat(value.w);
return this;
}
public void WriteObject(Type type, object value)
{
if (WriteCasters.TryGetValue(type, out var value2))
{
value2(this, value);
return;
}
throw new Exception($"Could not write value of type '{type}' as it is unsupported!");
}
public byte ReadByte()
{
if (buffer.Count > readPos)
{
byte result = readableBuffer[readPos];
readPos++;
return result;
}
throw new Exception("Could not read value of type 'byte'!");
}
public byte[] ReadBytes()
{
int num = ReadInt();
if (num == 0)
{
return new byte[0];
}
if (buffer.Count > readPos)
{
byte[] result = buffer.GetRange(readPos, num).ToArray();
readPos += num;
return result;
}
throw new Exception("Could not read value of type 'byte[]'!");
}
public bool[] ReadBools()
{
int num = ReadInt();
if (buffer.Count > readPos)
{
bool[] array = new bool[num];
for (int i = 0; i < num; i++)
{
byte b = buffer[readPos + i];
array[i] = b == 1;
}
readPos += num;
return array;
}
throw new Exception("Could not read value of type 'bool[]'!");
}
public short ReadShort()
{
if (buffer.Count > readPos)
{
short result = BitConverter.ToInt16(readableBuffer, readPos);
readPos += 2;
return result;
}
throw new Exception("Could not read value of type 'short'!");
}
public ushort ReadUShort()
{
if (buffer.Count > readPos)
{
ushort result = BitConverter.ToUInt16(readableBuffer, readPos);
readPos += 2;
return result;
}
throw new Exception("Could not read value of type 'short'!");
}
public int ReadInt()
{
if (buffer.Count > readPos)
{
int result = BitConverter.ToInt32(readableBuffer, readPos);
readPos += 4;
return result;
}
throw new Exception("Could not read value of type 'int'!");
}
public uint ReadUInt()
{
if (buffer.Count > readPos)
{
uint result = BitConverter.ToUInt32(readableBuffer, readPos);
readPos += 4;
return result;
}
throw new Exception("Could not read value of type 'uint'!");
}
public long ReadLong()
{
if (buffer.Count > readPos)
{
long result = BitConverter.ToInt64(readableBuffer, readPos);
readPos += 8;
return result;
}
throw new Exception("Could not read value of type 'long'!");
}
public ulong ReadULong()
{
if (buffer.Count > readPos)
{
ulong result = BitConverter.ToUInt64(readableBuffer, readPos);
readPos += 8;
return result;
}
throw new Exception("Could not read value of type 'ulong'!");
}
public float ReadFloat()
{
if (buffer.Count > readPos)
{
float result = BitConverter.ToSingle(readableBuffer, readPos);
readPos += 4;
return result;
}
throw new Exception("Could not read value of type 'float'!");
}
public bool ReadBool()
{
if (buffer.Count > readPos)
{
bool result = BitConverter.ToBoolean(readableBuffer, readPos);
readPos++;
return result;
}
throw new Exception("Could not read value of type 'bool'!");
}
public string ReadString()
{
try
{
int num = ReadInt();
string @string = Encoding.UTF8.GetString(readableBuffer, readPos, num);
if (@string.Length > 0)
{
readPos += num;
}
return @string;
}
catch
{
throw new Exception("Could not read value of type 'string'!");
}
}
public Vector3 ReadVector3()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
return new Vector3(ReadFloat(), ReadFloat(), ReadFloat());
}
public Quaternion ReadQuaternion()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
return new Quaternion(ReadFloat(), ReadFloat(), ReadFloat(), ReadFloat());
}
public object ReadObject(Type type)
{
if (ReadCasters.TryGetValue(type, out var value))
{
return value(this);
}
throw new Exception($"Could not read value of type '{type}' as it is unsupported!");
}
public int GetSize()
{
return readableBuffer.Length;
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
buffer = null;
readableBuffer = null;
readPos = 0;
}
disposed = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
public enum ReliableType
{
Unreliable,
Reliable,
UnreliableNoDelay
}
public static class MyceliumNetwork
{
private class MessageHandler
{
public object Target;
public MethodInfo Method;
public ParameterInfo[] Parameters;
public bool TakesInfo;
public int Mask;
}
private const int CHANNEL = 120;
private static List<string> lobbyDataKeys = new List<string>();
private static List<string> playerDataKeys = new List<string>();
private static Dictionary<CSteamID, Dictionary<string, string>> lastPlayerData = new Dictionary<CSteamID, Dictionary<string, string>>();
private static Dictionary<string, string> lastLobbyData = new Dictionary<string, string>();
private static Callback<LobbyEnter_t> _c2;
private static Callback<LobbyCreated_t> _c3;
private static Callback<LobbyChatUpdate_t> _c4;
private static Callback<LobbyDataUpdate_t> _c5;
private const int MAX_MESSAGES = 500;
private static IntPtr[] outMessages = new IntPtr[500];
private static Dictionary<uint, Dictionary<string, List<MessageHandler>>> rpcs = new Dictionary<uint, Dictionary<string, List<MessageHandler>>>();
public static CSteamID[] Players { get; private set; } = (CSteamID[])(object)new CSteamID[0];
public static int PlayerCount => SteamMatchmaking.GetNumLobbyMembers(Lobby);
public static int MaxPlayers => SteamMatchmaking.GetLobbyMemberLimit(Lobby);
public static CSteamID LobbyHost => SteamMatchmaking.GetLobbyOwner(Lobby);
public static bool IsHost => SteamMatchmaking.GetLobbyOwner(Lobby) == SteamUser.GetSteamID();
public static CSteamID Lobby { get; private set; }
public static bool InLobby { get; private set; }
public static event Action LobbyCreated;
public static event Action LobbyEntered;
public static event Action LobbyLeft;
public static event Action<EResult> LobbyCreationFailed;
public static event Action<CSteamID> PlayerEntered;
public static event Action<CSteamID> PlayerLeft;
public static event Action<CSteamID, List<string>> PlayerDataUpdated;
public static event Action<List<string>> LobbyDataUpdated;
public static void Initialize()
{
_c2 = Callback<LobbyEnter_t>.Create((DispatchDelegate<LobbyEnter_t>)OnLobbyEnter);
_c3 = Callback<LobbyCreated_t>.Create((DispatchDelegate<LobbyCreated_t>)OnLobbyCreated);
_c4 = Callback<LobbyChatUpdate_t>.Create((DispatchDelegate<LobbyChatUpdate_t>)OnLobbyChatUpdate);
_c5 = Callback<LobbyDataUpdate_t>.Create((DispatchDelegate<LobbyDataUpdate_t>)OnLobbyDataUpdate);
}
private static void OnLobbyEnter(LobbyEnter_t param)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
RugLogger.Log($"Entering lobby {param.m_ulSteamIDLobby}");
Lobby = new CSteamID(param.m_ulSteamIDLobby);
InLobby = true;
RefreshPlayerList();
MyceliumNetwork.LobbyEntered?.Invoke();
}
internal static void OnLobbyLeft()
{
lastLobbyData.Clear();
lastPlayerData.Clear();
InLobby = false;
MyceliumNetwork.LobbyLeft?.Invoke();
}
private static void OnLobbyCreated(LobbyCreated_t param)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Invalid comparison between Unknown and I4
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
RugLogger.Log($"Created lobby {param.m_eResult}");
if ((int)param.m_eResult == 1)
{
Lobby = new CSteamID(param.m_ulSteamIDLobby);
InLobby = true;
RefreshPlayerList();
MyceliumNetwork.LobbyCreated?.Invoke();
}
else
{
MyceliumNetwork.LobbyCreationFailed?.Invoke(param.m_eResult);
}
}
private static void OnLobbyChatUpdate(LobbyChatUpdate_t param)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected I4, but got Unknown
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Invalid comparison between Unknown and I4
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Invalid comparison between Unknown and I4
CSteamID obj = default(CSteamID);
((CSteamID)(ref obj))..ctor(param.m_ulSteamIDUserChanged);
RefreshPlayerList();
EChatMemberStateChange val = (EChatMemberStateChange)param.m_rgfChatMemberStateChange;
switch (val - 1)
{
default:
if ((int)val != 8 && (int)val != 16)
{
return;
}
break;
case 0:
MyceliumNetwork.PlayerEntered?.Invoke(obj);
return;
case 1:
case 3:
break;
case 2:
return;
}
MyceliumNetwork.PlayerLeft?.Invoke(obj);
}
private static void RefreshPlayerList()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: 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)
Players = (CSteamID[])(object)new CSteamID[SteamMatchmaking.GetNumLobbyMembers(Lobby)];
for (int i = 0; i < Players.Length; i++)
{
CSteamID lobbyMemberByIndex = SteamMatchmaking.GetLobbyMemberByIndex(Lobby, i);
Players[i] = lobbyMemberByIndex;
}
}
public static void RPCTargetMasked(uint modId, string methodName, CSteamID target, ReliableType reliable, int mask, params object[] parameters)
{
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
Message message = new Message(modId, methodName, mask);
MessageHandler messageHandler = GetMessageHandlers(modId, methodName)[0];
int num = messageHandler.Parameters.Length;
if (messageHandler.TakesInfo)
{
num--;
}
if (num != parameters.Length)
{
throw new Exception($"RPC call {modId}: {methodName} has an invalid number of parameters (it has {parameters.Length}, but it should have {num})");
}
for (int i = 0; i < num; i++)
{
if (messageHandler.Parameters[i].ParameterType != parameters[i].GetType())
{
throw new Exception($"RPC call {modId}: {methodName} has a mismatched parameter type ({parameters[i].GetType()} should be {messageHandler.Parameters[i].ParameterType}) for {messageHandler.Parameters[i].Name}");
}
message.WriteObject(messageHandler.Parameters[i].ParameterType, parameters[i]);
}
SendBytes(message.ToArray(), target, reliable);
}
public static void RPCTarget(uint modId, string methodName, CSteamID target, ReliableType reliable, params object[] parameters)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
RPCTargetMasked(modId, methodName, target, reliable, 0, parameters);
}
public static void RPCMasked(uint modId, string methodName, ReliableType reliable, int mask, params object[] parameters)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < Players.Length; i++)
{
RPCTargetMasked(modId, methodName, Players[i], reliable, mask, parameters);
}
}
public static void RPC(uint modId, string methodName, ReliableType reliable, params object[] parameters)
{
RPCMasked(modId, methodName, reliable, 0, parameters);
}
public static void RegisterLobbyDataKey(string key)
{
if (lobbyDataKeys.Contains(key))
{
RugLogger.LogError("Lobby data key " + key + " is already defined");
}
else
{
lobbyDataKeys.Add(key);
}
}
public static void RegisterPlayerDataKey(string key)
{
if (playerDataKeys.Contains(key))
{
RugLogger.LogError("Player data key " + key + " is already defined");
}
else
{
playerDataKeys.Add(key);
}
}
private static void OnLobbyDataUpdate(LobbyDataUpdate_t param)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: 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_0042: 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_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
if (!InLobby || param.m_ulSteamIDLobby != Lobby.m_SteamID)
{
return;
}
if (param.m_ulSteamIDLobby == param.m_ulSteamIDMember)
{
List<string> list = new List<string>();
for (int i = 0; i < lobbyDataKeys.Count; i++)
{
string text = lobbyDataKeys[i];
string lobbyData = SteamMatchmaking.GetLobbyData(Lobby, text);
if (lastLobbyData.ContainsKey(text))
{
if (!lastLobbyData[text].Equals(lobbyData))
{
list.Add(text);
}
}
else
{
list.Add(text);
}
lastLobbyData[text] = lobbyData;
}
if (list.Count > 0)
{
MyceliumNetwork.LobbyDataUpdated?.Invoke(list);
}
return;
}
CSteamID val = default(CSteamID);
((CSteamID)(ref val))..ctor(param.m_ulSteamIDMember);
if (!lastPlayerData.ContainsKey(val))
{
lastPlayerData[val] = new Dictionary<string, string>();
}
List<string> list2 = new List<string>();
for (int j = 0; j < playerDataKeys.Count; j++)
{
string text2 = playerDataKeys[j];
string lobbyMemberData = SteamMatchmaking.GetLobbyMemberData(Lobby, val, text2);
if (lastPlayerData[val].ContainsKey(text2))
{
if (!lastPlayerData[val][text2].Equals(lobbyMemberData))
{
list2.Add(text2);
}
}
else
{
list2.Add(text2);
}
lastPlayerData[val][text2] = lobbyMemberData;
}
if (list2.Count > 0)
{
MyceliumNetwork.PlayerDataUpdated?.Invoke(val, list2);
}
}
public static void SetLobbyData(string key, object value)
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
if (!InLobby)
{
RugLogger.LogError("Cannot set lobby data when not in lobby.");
return;
}
if (!lobbyDataKeys.Contains(key))
{
RugLogger.LogWarning("Accessing lobby data for unregistered key '" + key + "'. This might not exist.");
}
if (!SteamMatchmaking.SetLobbyData(Lobby, key, (string)Convert.ChangeType(value, typeof(string), CultureInfo.InvariantCulture)))
{
RugLogger.LogError("Error setting lobby data.");
}
}
public static bool HasLobbyData(string key)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
if (!InLobby)
{
RugLogger.LogError("Cannot get lobby data when not in lobby.");
return false;
}
if (!lobbyDataKeys.Contains(key))
{
RugLogger.LogWarning("Accessing lobby data for unregistered key '" + key + "'. This might not exist.");
}
string lobbyData = SteamMatchmaking.GetLobbyData(Lobby, key.ToString());
return !string.IsNullOrEmpty(lobbyData);
}
public static T GetLobbyData<T>(string key)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
if (!InLobby)
{
RugLogger.LogError("Cannot get lobby data when not in lobby.");
return default(T);
}
if (!lobbyDataKeys.Contains(key))
{
RugLogger.LogWarning("Accessing lobby data for unregistered key '" + key + "'. This might not exist.");
}
string lobbyData = SteamMatchmaking.GetLobbyData(Lobby, key.ToString());
try
{
return (T)Convert.ChangeType(lobbyData, typeof(T), CultureInfo.InvariantCulture);
}
catch (Exception ex)
{
RugLogger.LogError("Could not parse lobby data [" + key + ", " + lobbyData + "] as " + typeof(T).Name + ": " + ex.Message);
}
return default(T);
}
public static void SetPlayerData(string key, object value)
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
if (!InLobby)
{
RugLogger.LogError("Cannot set player data when not in lobby.");
return;
}
if (!playerDataKeys.Contains(key))
{
RugLogger.LogWarning("Accessing player data for unregistered key '" + key + "'. This might not exist.");
}
SteamMatchmaking.SetLobbyMemberData(Lobby, key.ToString(), (string)Convert.ChangeType(value, typeof(string), CultureInfo.InvariantCulture));
}
public static bool HasPlayerData(CSteamID player, string key)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
if (!InLobby)
{
RugLogger.LogError("Cannot get player data when not in lobby.");
return false;
}
if (!playerDataKeys.Contains(key))
{
RugLogger.LogWarning("Accessing player data for unregistered key '" + key + "'. This might not exist.");
}
string lobbyMemberData = SteamMatchmaking.GetLobbyMemberData(Lobby, player, key.ToString());
return !string.IsNullOrEmpty(lobbyMemberData);
}
public static T GetPlayerData<T>(CSteamID player, string key)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
if (!InLobby)
{
RugLogger.LogError("Cannot get player data when not in lobby.");
return default(T);
}
if (!playerDataKeys.Contains(key))
{
RugLogger.LogWarning("Accessing player data for unregistered key '" + key + "'. This might not exist.");
}
string lobbyMemberData = SteamMatchmaking.GetLobbyMemberData(Lobby, player, key.ToString());
if (!string.IsNullOrEmpty(lobbyMemberData))
{
try
{
return (T)Convert.ChangeType(lobbyMemberData, typeof(T), CultureInfo.InvariantCulture);
}
catch (Exception ex)
{
RugLogger.LogError("Could not parse [" + key + ", " + lobbyMemberData + "] as " + typeof(T).Name + ": " + ex.Message);
}
}
return default(T);
}
private static void SendBytes(byte[] data, CSteamID target, ReliableType reliable)
{
//IL_002c: 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_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Invalid comparison between Unknown and I4
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
if (data.Length > Message.MaxSize)
{
RugLogger.LogError($"Size of message ({data.Length} bytes) is greater than the max allowed size ({Message.MaxSize}).");
return;
}
if (target == SteamUser.GetSteamID())
{
Message message = new Message(data);
HandleMessage(message, target);
return;
}
SteamNetworkingIdentity val = default(SteamNetworkingIdentity);
((SteamNetworkingIdentity)(ref val)).SetSteamID(target);
GCHandle gCHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr intPtr = gCHandle.AddrOfPinnedObject();
int num = 0;
switch (reliable)
{
case ReliableType.Unreliable:
num = 0;
break;
case ReliableType.Reliable:
num = 8;
break;
case ReliableType.UnreliableNoDelay:
num = 5;
break;
}
EResult val2 = SteamNetworkingMessages.SendMessageToUser(ref val, intPtr, (uint)data.Length, num | 0x20, 120);
if ((int)val2 != 1)
{
RugLogger.LogError($"Error sending message to user {target}: {val2}");
}
gCHandle.Free();
}
private static List<MessageHandler> GetMessageHandlers(uint modID, string methodName)
{
if (rpcs.TryGetValue(modID, out var value))
{
if (value.TryGetValue(methodName, out var value2))
{
return value2;
}
throw new Exception($"The RPC ({modID}: {methodName}) was not found");
}
throw new Exception(string.Format("The mod id {0} was not found (loaded mods: {1})", modID, string.Join(",", rpcs.Keys.ToArray())));
}
private static void HandleMessage(Message message, CSteamID sender)
{
//IL_0125: 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_009c: Unknown result type (might be due to invalid IL or missing references)
try
{
List<MessageHandler> messageHandlers = GetMessageHandlers(message.ModID, message.MethodName);
bool flag = false;
foreach (MessageHandler item in messageHandlers)
{
if (item.Mask == message.Mask)
{
object[] array = new object[item.Parameters.Length];
int num = (item.TakesInfo ? (array.Length - 1) : array.Length);
for (int i = 0; i < num; i++)
{
array[i] = message.ReadObject(item.Parameters[i].ParameterType);
}
if (item.TakesInfo)
{
array[item.Parameters.Length - 1] = new RPCInfo(sender);
}
item.Method.Invoke(item.Target, array);
flag = true;
}
}
if (!flag)
{
RugLogger.LogWarning($"Dropped RPC because no registered RPCs were found matching {message.ModID}: {message.MethodName}");
}
}
catch (Exception ex2)
{
string text;
try
{
text = message.GetDestination();
}
catch (Exception ex)
{
text = ex.Message;
}
RugLogger.LogError(string.Format("Error executing RPC from {0} ({1}):\n{2}\nFull exception:\n{3} {4}", (sender == SteamUser.GetSteamID()) ? "local loopback" : ((object)(CSteamID)(ref sender)).ToString(), text, ex2.InnerException, ex2, ex2.StackTrace));
}
}
public static void ReceiveMessages()
{
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: 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)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
int num = SteamNetworkingMessages.ReceiveMessagesOnChannel(120, outMessages, 500);
for (int i = 0; i < num; i++)
{
IntPtr intPtr = outMessages[i];
int num2 = Marshal.SizeOf(intPtr);
if (num2 > Message.MaxSize)
{
RugLogger.LogError($"Ignored message because its size was above the max ({num2}/{Message.MaxSize})");
SteamNetworkingMessage_t.Release(outMessages[i]);
continue;
}
SteamNetworkingMessage_t val = Marshal.PtrToStructure<SteamNetworkingMessage_t>(intPtr);
CSteamID steamID = ((SteamNetworkingIdentity)(ref val.m_identityPeer)).GetSteamID();
if (!Players.Contains(steamID))
{
SteamNetworkingMessage_t.Release(outMessages[i]);
continue;
}
byte[] array = new byte[val.m_cbSize];
Marshal.Copy(val.m_pData, array, 0, val.m_cbSize);
Message message = new Message(array);
try
{
HandleMessage(message, steamID);
}
catch (Exception ex2)
{
string text;
try
{
text = message.GetDestination();
}
catch (Exception ex)
{
text = ex.Message;
}
RugLogger.LogError($"Error executing RPC from {steamID} ({text}): {ex2.Message} {ex2.StackTrace}");
}
SteamNetworkingMessage_t.Release(outMessages[i]);
}
}
public static void RegisterNetworkObject(object obj, uint modId, int mask = 0)
{
Type type = obj.GetType();
int num = 0;
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
CustomRPCAttribute[] source = methodInfo.GetCustomAttributes(inherit: false).OfType<CustomRPCAttribute>().ToArray();
if (source.Any())
{
ParameterInfo[] parameters = methodInfo.GetParameters();
if (!rpcs.ContainsKey(modId))
{
rpcs[modId] = new Dictionary<string, List<MessageHandler>>();
}
if (!rpcs[modId].ContainsKey(methodInfo.Name))
{
rpcs[modId][methodInfo.Name] = new List<MessageHandler>();
}
rpcs[modId][methodInfo.Name].Add(new MessageHandler
{
Target = obj,
Method = methodInfo,
Parameters = parameters,
TakesInfo = (parameters.Length != 0 && parameters[^1].ParameterType == typeof(RPCInfo)),
Mask = mask
});
num++;
}
}
RugLogger.Log($"Registered {num} CustomRPCs for {modId}: {obj}.");
}
public static void DeregisterNetworkObject(object obj, uint modId, int mask = 0)
{
Type type = obj.GetType();
int num = 0;
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
CustomRPCAttribute[] source = methodInfo.GetCustomAttributes(inherit: false).OfType<CustomRPCAttribute>().ToArray();
if (!source.Any())
{
continue;
}
if (!rpcs.ContainsKey(modId))
{
RugLogger.Log($"Attempted to deregister RPCs for mod id {modId}, but no RPCs from that mod are loaded.");
return;
}
if (!rpcs[modId].ContainsKey(methodInfo.Name))
{
RugLogger.Log($"Attempted to deregister RPC {methodInfo.Name} for mod id {modId}, but no RPCs by that name are loaded.");
return;
}
MessageHandler[] array = rpcs[modId][methodInfo.Name].ToArray();
foreach (MessageHandler messageHandler in array)
{
if (messageHandler.Mask == mask)
{
rpcs[modId][methodInfo.Name].Remove(messageHandler);
}
}
num++;
}
RugLogger.Log($"Deregistered {num} CustomRPCs for {modId}: {obj}.");
}
}
public struct RPCInfo
{
public CSteamID SenderSteamID;
public RPCInfo(CSteamID senderSteamId)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
SenderSteamID = senderSteamId;
}
}
internal class PersistentGameObject : MonoBehaviour
{
private void Update()
{
MyceliumNetwork.ReceiveMessages();
}
}
[BepInPlugin("RugbugRedfern.MyceliumNetworking", "Mycelium Networking", "1.0.14")]
public class PluginLoader : BaseUnityPlugin
{
private static bool initialized;
private void Awake()
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
if (!initialized)
{
initialized = true;
RugLogger.Initialize("RugbugRedfern.MyceliumNetworking");
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
RugLogger.Log("MyceliumNetworking Starting 1.0.14");
MyceliumNetwork.Initialize();
GameObject val = new GameObject("MyceliumNetworking Persistent");
val.AddComponent<PersistentGameObject>();
((Object)val).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)val);
}
}
}
public static class RugLogger
{
public static ManualLogSource logSource;
public static void Initialize(string modGUID)
{
logSource = Logger.CreateLogSource(modGUID);
}
public static void Log(object message)
{
logSource.LogInfo(message);
}
public static void LogError(object message)
{
logSource.LogError(message);
}
public static void LogWarning(object message)
{
logSource.LogWarning(message);
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "RugbugRedfern.MyceliumNetworking";
public const string PLUGIN_NAME = "Mycelium Networking";
public const string PLUGIN_VERSION = "1.0.14";
}
}
namespace MyceliumNetworking.Patches
{
[HarmonyPatch(typeof(SteamLobbyHandler))]
internal class SteamLobbyHandlerPatches
{
[HarmonyPatch("LeaveLobby")]
[HarmonyPostfix]
private static void LeaveLobbyPatch()
{
RugLogger.Log("Patching SteamLobbyHandler.LeaveLobby");
MyceliumNetwork.OnLobbyLeft();
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}