Decompiled source of CSync v3.0.1

BepInEx/plugins/CSync/CSync.dll

Decompiled 2 weeks ago
using 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)
		{
		}
	}
}