Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of CSync v3.0.1
BepInEx/plugins/CSync/CSync.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CSync.Core; using CSync.Lib; using CSync.Patches; using CSync.Util; using HarmonyLib; using Microsoft.CodeAnalysis; 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: AssemblyCompany("Owen3H")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Configuration file syncing library for BepInEx.\r\nAllows serialization of a ConfigEntry with a drop in replacement.\r\n\r\nThe wiki/usage guide can be found on GitHub.\r\nhttps://github.com/Owen3H/CSync/wiki\r\n ")] [assembly: AssemblyFileVersion("3.0.0.0")] [assembly: AssemblyInformationalVersion("3.0.0+a03bd481a153bbd87607e6805f3162820eb4222a")] [assembly: AssemblyProduct("CSync")] [assembly: AssemblyTitle("CSync")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Owen3H/CSync.git")] [assembly: NeutralResourcesLanguage("en-GB")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.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 CSync { [BepInPlugin("io.github.CSync", "CSync", "3.0.0")] public class Plugin : BaseUnityPlugin { public const string GUID = "io.github.CSync"; public const string NAME = "CSync"; public const string VERSION = "3.0.0"; private Harmony Patcher; internal static ManualLogSource Logger { get; private set; } internal static CSyncConfig Config { get; private set; } private void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Config = new CSyncConfig(((BaseUnityPlugin)this).Config); if (!Config.ENABLE_PATCHING.Value) { return; } try { Patcher = new Harmony("io.github.CSync"); Patcher.PatchAll(typeof(NetworkManagerPatch)); } catch (Exception arg) { Logger.LogError((object)$"Failed to apply necessary patches!!\n{arg}"); } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "CSync"; public const string PLUGIN_NAME = "CSync"; public const string PLUGIN_VERSION = "3.0.0"; } } namespace CSync.Util { [Serializable] public class ByteSerializer<T> { [NonSerialized] private static readonly DataContractSerializer Serializer = new DataContractSerializer(typeof(T)); public static int IntSize => 4; public static byte[] SerializeToBytes(T val) { using MemoryStream memoryStream = new MemoryStream(); Serializer.WriteObject(memoryStream, val); return memoryStream.ToArray(); } public static T DeserializeFromBytes(byte[] data) { using MemoryStream stream = new MemoryStream(data); try { return (T)Serializer.ReadObject(stream); } catch (Exception) { return default(T); } } } public static class Extensions { public static SyncedEntry<V> BindSyncedEntry<V>(this ConfigFile cfg, ConfigDefinition definition, V defaultVal, ConfigDescription desc = null) { return cfg.Bind<V>(definition, defaultVal, desc).ToSyncedEntry<V>(); } public static SyncedEntry<V> BindSyncedEntry<V>(this ConfigFile cfg, ConfigDefinition definition, V defaultValue, string desc) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown return cfg.Bind<V>(definition, defaultValue, new ConfigDescription(desc, (AcceptableValueBase)null, Array.Empty<object>())).ToSyncedEntry<V>(); } public static SyncedEntry<V> BindSyncedEntry<V>(this ConfigFile cfg, string section, string key, V defaultValue, ConfigDescription desc = null) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown return cfg.Bind<V>(new ConfigDefinition(section, key), defaultValue, desc).ToSyncedEntry<V>(); } public static SyncedEntry<V> BindSyncedEntry<V>(this ConfigFile cfg, string section, string key, V defaultValue, string desc) { //IL_0003: 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_001b: Expected O, but got Unknown //IL_001b: Expected O, but got Unknown return cfg.Bind<V>(new ConfigDefinition(section, key), defaultValue, new ConfigDescription(desc, (AcceptableValueBase)null, Array.Empty<object>())).ToSyncedEntry<V>(); } public static SyncedEntry<V> ToSyncedEntry<V>(this ConfigEntry<V> entry) { return new SyncedEntry<V>(entry); } public static T GetObject<T>(this SerializationInfo info, string key) { return (T)info.GetValue(key, typeof(T)); } internal static ConfigEntry<V> Reconstruct<V>(this ConfigFile cfg, SerializationInfo info) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown ConfigDefinition val = new ConfigDefinition(info.GetString("Section"), info.GetString("Key")); ConfigDescription val2 = new ConfigDescription(info.GetString("Description"), (AcceptableValueBase)null, Array.Empty<object>()); return cfg.Bind<V>(val, info.GetObject<V>("DefaultValue"), val2); } internal static void SendMessage(this FastBufferWriter stream, string guid, string label, ulong clientId = 0uL) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) bool flag = ((FastBufferWriter)(ref stream)).Capacity > 1300; NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(guid + "_" + label, clientId, stream, (NetworkDelivery)(flag ? 4 : 2)); } } } namespace CSync.Util.Types { [Serializable] public class SColor { public float r; public float g; public float b; public float a; public static implicit operator Color(SColor col) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Color(col.r, col.g, col.b, col.a); } public SColor(Color color) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) SetRGBA(color); } public SColor(string hex) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Color rGBA = default(Color); ColorUtility.TryParseHtmlString(hex, ref rGBA); SetRGBA(rGBA); } public void SetRGBA(Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0025: Unknown result type (might be due to invalid IL or missing references) r = color.r; g = color.g; b = color.b; a = color.a; } public Color AsColor() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Color(r, g, b, a); } public string AsHex() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ColorUtility.ToHtmlStringRGBA(AsColor()); } } [Serializable] public class SQuaternion { public float x; public float y; public float z; public float w; public SQuaternion(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; base..ctor(); } public override string ToString() { return $"[{x}, {y}, {z}, {w}]"; } public static implicit operator Quaternion(SQuaternion sq) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Quaternion(sq.x, sq.y, sq.z, sq.w); } public static implicit operator SQuaternion(Quaternion q) { //IL_0000: 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_000c: 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) return new SQuaternion(q.x, q.y, q.z, q.w); } } [Serializable] public class SVector2 { public float x; public float y; public SVector2(float _x, float _y) { x = _x; y = _y; base..ctor(); } public override string ToString() { return $"[{x}, {y}]"; } public static implicit operator SVector2(SVector3 sv2) { return new SVector2(sv2.x, sv2.y); } public static implicit operator SVector2(Vector3 v2) { //IL_0000: 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) return new SVector2(v2.x, v2.y); } } [Serializable] public class SVector3 { public float x; public float y; public float z; public SVector3(float _x, float _y, float _z) { x = _x; y = _y; z = _z; base..ctor(); } public override string ToString() { return $"[{x}, {y}, {z}]"; } public static implicit operator Vector3(SVector3 sv3) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(sv3.x, sv3.y, sv3.z); } public static implicit operator SVector3(Vector3 v3) { //IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references) return new SVector3(v3.x, v3.y, v3.z); } } [Serializable] public class SVector4 { public float x; public float y; public float z; public float w; public SVector4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; base..ctor(); } public override string ToString() { return $"[{x}, {y}, {z}, {w}]"; } public static implicit operator Vector4(SVector4 sv4) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Vector4(sv4.x, sv4.y, sv4.z, sv4.w); } public static implicit operator SVector4(Vector4 v4) { //IL_0000: 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_000c: 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) return new SVector4(v4.x, v4.y, v4.z, v4.w); } } } namespace CSync.Patches { [HarmonyPatch(typeof(NetworkConnectionManager))] internal class NetworkManagerPatch { private static bool HasAuthority { get { if (!NetworkManager.Singleton.IsHost) { return NetworkManager.Singleton.IsServer; } return true; } } [HarmonyPostfix] [HarmonyPatch("InvokeOnClientConnectedCallback")] private static void OnConnected(ulong clientId) { ConfigManager.SyncInstances(); if (!HasAuthority) { Plugin.Logger.LogDebug((object)$"Client connected with id: {clientId}"); } } } } namespace CSync.Lib { public class ConfigManager { internal static Dictionary<string, ConfigFile> FileCache = new Dictionary<string, ConfigFile>(); internal static Dictionary<string, ISynchronizable> Instances = new Dictionary<string, ISynchronizable>(); internal static ConfigFile GetConfigFile(string fileName) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (!FileCache.TryGetValue(fileName, out var value)) { value = new ConfigFile(Path.Combine(Paths.ConfigPath, fileName), false); FileCache.Add(fileName, value); } return value; } public static void Register<T>(T config) where T : SyncedConfig<T>, ISynchronizable { string gUID = config.GUID; if (config == null) { Plugin.Logger.LogError((object)("An error occurred registering config: " + gUID + "\nConfig instance cannot be null!")); } if (Instances.ContainsKey(gUID)) { Plugin.Logger.LogWarning((object)("Attempted to register config `" + gUID + "` after it has already been registered!")); return; } config.InitInstance(config); Instances.Add(gUID, config); } internal static void SyncInstances() { CollectionExtensions.Do<ISynchronizable>((IEnumerable<ISynchronizable>)Instances.Values, (Action<ISynchronizable>)delegate(ISynchronizable i) { i.RegisterMessages(); }); } internal static void RevertSyncedInstances() { CollectionExtensions.Do<ISynchronizable>((IEnumerable<ISynchronizable>)Instances.Values, (Action<ISynchronizable>)delegate(ISynchronizable i) { i.RevertSync(); }); } } public interface ISynchronizable { void RegisterMessages(); void RequestSync(); void RevertSync(); } [Serializable] public class SyncedConfig<T> : SyncedInstance<T>, ISynchronizable where T : class { public readonly string GUID; [NonSerialized] public Action<ulong> SyncRequested; [NonSerialized] public Action SyncReceived; internal SyncedEntry<bool> SYNC_TO_CLIENTS { get; private set; } public SyncedConfig(string guid) { GUID = guid; base..ctor(); } private static void LogErr(string str) { Plugin.Logger.LogError((object)str); } private static void LogDebug(string str) { Plugin.Logger.LogDebug((object)str); } private void RegisterMessage(string name, HandleNamedMessageDelegate callback) { SyncedInstance<T>.MessageManager.RegisterNamedMessageHandler(GUID + "_" + name, callback); } internal void OnSyncRequested(ulong clientId) { SyncRequested?.Invoke(clientId); } internal void OnSyncReceived() { SyncReceived?.Invoke(); } protected void EnableHostSyncControl(SyncedEntry<bool> hostSyncControlOption) { SYNC_TO_CLIENTS = hostSyncControlOption; hostSyncControlOption.SettingChanged += delegate { SYNC_TO_CLIENTS = hostSyncControlOption; }; } void ISynchronizable.RegisterMessages() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (SyncedInstance<T>.IsHost) { RegisterMessage("OnRequestConfigSync", new HandleNamedMessageDelegate(OnRequestSync)); return; } RegisterMessage("OnHostDisabledSyncing", new HandleNamedMessageDelegate(OnHostDisabledSyncing)); RegisterMessage("OnReceiveConfigSync", new HandleNamedMessageDelegate(OnReceiveSync)); RequestSync(); } void ISynchronizable.RequestSync() { RequestSync(); } private void RequestSync() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance<T>.IsClient) { return; } FastBufferWriter stream = default(FastBufferWriter); ((FastBufferWriter)(ref stream))..ctor(ByteSerializer<T>.IntSize, (Allocator)2, -1); try { stream.SendMessage(GUID, "OnRequestConfigSync", 0uL); } finally { ((IDisposable)(FastBufferWriter)(ref stream)).Dispose(); } } internal void OnRequestSync(ulong clientId, FastBufferReader _) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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) if (!SyncedInstance<T>.IsHost) { return; } OnSyncRequested(clientId); if (SYNC_TO_CLIENTS != null && !SYNC_TO_CLIENTS) { FastBufferWriter stream = default(FastBufferWriter); ((FastBufferWriter)(ref stream))..ctor(ByteSerializer<T>.IntSize, (Allocator)2, -1); try { stream.SendMessage(GUID, "OnHostDisabledSyncing", clientId); LogDebug(GUID + " - The host (you) has syncing disabled! Informing other clients.."); return; } finally { ((IDisposable)(FastBufferWriter)(ref stream)).Dispose(); } } LogDebug($"{GUID} - Config sync request received from client: {clientId}"); byte[] array = ByteSerializer<T>.SerializeToBytes(SyncedInstance<T>.Instance); int num = array.Length; FastBufferWriter stream2 = default(FastBufferWriter); ((FastBufferWriter)(ref stream2))..ctor(num + ByteSerializer<T>.IntSize, (Allocator)2, -1); try { ((FastBufferWriter)(ref stream2)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref stream2)).WriteBytesSafe(array, -1, 0); stream2.SendMessage(GUID, "OnReceiveConfigSync", clientId); } catch (Exception arg) { LogErr($"{GUID} - Error occurred syncing config with client: {clientId}\n{arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref stream2)).Dispose(); } } internal void OnReceiveSync(ulong _, FastBufferReader reader) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) OnSyncReceived(); if (!((FastBufferReader)(ref reader)).TryBeginRead(ByteSerializer<T>.IntSize)) { LogErr(GUID + " - Config sync error: Could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { LogErr(GUID + " - Config sync error: Host could not sync."); return; } byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); try { SyncInstance(data); } catch (Exception arg) { LogErr($"{GUID} - Error syncing config instance!\n{arg}"); } } internal void OnHostDisabledSyncing(ulong _, FastBufferReader reader) { OnSyncCompleted(success: false); LogDebug(GUID + " - The host has disabled syncing. Invoking the SyncComplete event.."); } } [Serializable] public class SyncedEntry<V> : ISerializable { [NonSerialized] public readonly ConfigEntry<V> Entry; private string ConfigFileName => Path.GetFileName(((ConfigEntryBase)Entry).ConfigFile.ConfigFilePath); public string Key => ((ConfigEntryBase)Entry).Definition.Key; public string Section => ((ConfigEntryBase)Entry).Definition.Section; public string Description => ((ConfigEntryBase)Entry).Description.Description; public object DefaultValue => ((ConfigEntryBase)Entry).DefaultValue; public V Value { get { return Entry.Value; } set { Entry.Value = value; } } public event EventHandler SettingChanged { add { Entry.SettingChanged += value; } remove { Entry.SettingChanged -= value; } } public static implicit operator V(SyncedEntry<V> e) { return e.Value; } public SyncedEntry(ConfigEntry<V> cfgEntry) { Entry = cfgEntry; } private SyncedEntry(SerializationInfo info, StreamingContext ctx) { ConfigFile configFile = ConfigManager.GetConfigFile(info.GetString("ConfigFileName")); Entry = configFile.Reconstruct<V>(info); Value = info.GetObject<V>("CurrentValue"); } public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("ConfigFileName", ConfigFileName); info.AddValue("Key", Key); info.AddValue("Section", Section); info.AddValue("Description", Description); info.AddValue("DefaultValue", DefaultValue); info.AddValue("CurrentValue", Value); } public override string ToString() { return $"Key: {Key}\nDefault Value: {DefaultValue}\nCurrent Value: {Value}"; } } [Serializable] public class SyncedInstance<T> : ByteSerializer<T> where T : class { [NonSerialized] public Action<bool> SyncComplete; [NonSerialized] public Action SyncReverted; public static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager; public static bool IsClient => NetworkManager.Singleton.IsClient; public static bool IsHost => NetworkManager.Singleton.IsHost; public static T Default { get; private set; } public static T Instance { get; private set; } internal void OnSyncCompleted(bool success) { SyncComplete?.Invoke(success); } internal void OnSyncReverted() { SyncReverted?.Invoke(); } public void InitInstance(T instance) { Default = instance; Instance = instance; } public void SyncInstance(byte[] data) { if (data == null) { throw new ArgumentNullException("data", "Null value was passed the `SyncInstance` method.\nUnless you know what you are doing, calling this method is not advised!"); } Instance = ByteSerializer<T>.DeserializeFromBytes(data); OnSyncCompleted(Instance != null); } public void RevertSync() { Instance = Default; OnSyncReverted(); } } } namespace CSync.Core { internal class CSyncConfig { public ConfigEntry<bool> ENABLE_PATCHING { get; } = cfg.Bind<bool>("io.github.CSync", "bEnablePatching", true, "Whether to let CSync apply necessary patches.\nIt is not recommended to disable this unless all of your mods implement their own patches for syncing."); public ConfigEntry<bool> GAME_DETECTION { get; } = cfg.Bind<bool>("io.github.CSync", "bGameDetection", true, "Should CSync automatically apply patches specific to the game currently running?\nTurning this off will not affect the core functionality of CSync, in some cases, it may solve issues."); public CSyncConfig(ConfigFile cfg) { } } }