Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
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) { } } }