Decompiled source of EasySync v0.0.2

EasySync.dll

Decompiled 10 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EasySync")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EasySync")]
[assembly: AssemblyTitle("EasySync")]
[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 EasySync
{
	[BepInPlugin("EasySync", "EasySync", "0.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class EasySyncPlugin : BaseUnityPlugin
	{
		public const string MOD_ID = "EasySync";

		public const string MOD_NAME = "EasySync";

		public const string MOD_VERSION = "0.0.2";

		private static readonly Harmony _harmony = new Harmony("EasySync");

		public static EasySyncPlugin instance;

		private ManualLogSource logSource => ((BaseUnityPlugin)this).Logger;

		private void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin EasySync is loaded!");
			instance = this;
			_harmony.PatchAll(typeof(Patches));
		}

		internal static bool ConditionLog(string message, bool condition = true, LogLevel logLevel = 16)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (condition)
			{
				instance.logSource.Log(logLevel, (object)message);
			}
			return condition;
		}
	}
	public class Patches
	{
		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		private static void PlayerControllerBConnectClientToPlayerObjectPostFix(PlayerControllerB __instance)
		{
			SyncManager.SyncAllInstances();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")]
		private static void GameNetworkManagerStartDisconnectPostFix()
		{
			SyncManager.RevertSyncAllInstances();
		}
	}
	public static class SyncManager
	{
		public readonly struct SyncedInstanceContainer
		{
			private readonly object instance;

			private readonly string GUID;

			private readonly MethodInfo initInstanceMethod;

			private readonly MethodInfo revertSyncMethod;

			private readonly MethodInfo serializeToBytesMethod;

			private readonly MethodInfo syncInstanceMethod;

			private readonly PropertyInfo instanceProperty;

			private readonly PropertyInfo defaultProperty;

			private readonly PropertyInfo intSizeProperty;

			private readonly PropertyInfo messageManagerProperty;

			private readonly PropertyInfo isClientProperty;

			private readonly PropertyInfo isHostProperty;

			private readonly FieldInfo syncedField;

			internal readonly bool isValid;

			public object Instance => instanceProperty.GetValue(null);

			public object Default => defaultProperty.GetValue(null);

			public int IntSize => (int)intSizeProperty.GetValue(null);

			public CustomMessagingManager MessageManager => (CustomMessagingManager)messageManagerProperty.GetValue(null);

			public bool IsClient => (bool)isClientProperty.GetValue(null);

			public bool IsHost => (bool)isHostProperty.GetValue(null);

			internal bool Synced
			{
				get
				{
					return (bool)syncedField.GetValue(null);
				}
				set
				{
					syncedField.SetValue(null, value);
				}
			}

			internal SyncedInstanceContainer(object instance, string GUID)
			{
				this.instance = instance;
				Type baseType = instance.GetType().BaseType;
				this.GUID = GUID;
				BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public;
				int i = 0;
				instanceProperty = baseType.GetProperty("Instance", bindingAttr);
				defaultProperty = baseType.GetProperty("Default", bindingAttr);
				initInstanceMethod = baseType.GetMethod("InitInstance", BindingFlags.Instance | BindingFlags.Public);
				revertSyncMethod = baseType.GetMethod("RevertSync", bindingAttr);
				serializeToBytesMethod = baseType.BaseType.GetMethod("SerializeToBytes", bindingAttr);
				syncInstanceMethod = baseType.GetMethod("SyncInstance", bindingAttr);
				intSizeProperty = baseType.BaseType.GetProperty("IntSize", bindingAttr);
				messageManagerProperty = baseType.GetProperty("MessageManager", bindingAttr);
				isClientProperty = baseType.GetProperty("IsClient", bindingAttr);
				isHostProperty = baseType.GetProperty("IsHost", bindingAttr);
				syncedField = baseType.GetField("Synced", bindingAttr);
				ScreamIfNull(instanceProperty);
				ScreamIfNull(defaultProperty);
				ScreamIfNull(initInstanceMethod);
				ScreamIfNull(revertSyncMethod);
				ScreamIfNull(serializeToBytesMethod);
				ScreamIfNull(syncInstanceMethod);
				ScreamIfNull(intSizeProperty);
				ScreamIfNull(messageManagerProperty);
				ScreamIfNull(isClientProperty);
				ScreamIfNull(isHostProperty);
				ScreamIfNull(syncedField);
				isValid = instanceProperty != null && defaultProperty != null && initInstanceMethod != null && revertSyncMethod != null && intSizeProperty != null && messageManagerProperty != null && isClientProperty != null && isHostProperty != null && syncedField != null;
				void ScreamIfNull(object obj)
				{
					i++;
					EasySyncPlugin.ConditionLog($"VARIABLE AT INDEX {i} IS NULL!!!", obj == null, (LogLevel)2);
				}
			}

			internal void InitInstance()
			{
				initInstanceMethod.Invoke(instance, new object[1] { instance });
			}

			public void RevertSync()
			{
				revertSyncMethod.Invoke(null, null);
			}

			private byte[] SerializeToBytes(object inst)
			{
				return (byte[])serializeToBytesMethod.Invoke(null, new object[1] { inst });
			}

			private void SyncInstance(byte[] data)
			{
				syncInstanceMethod.Invoke(null, new object[1] { data });
			}

			internal void BeginSync()
			{
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Expected O, but got Unknown
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Expected O, but got Unknown
				if (IsHost)
				{
					MessageManager.RegisterNamedMessageHandler(GUID + "_OnRequestConfigSync", new HandleNamedMessageDelegate(OnRequestSync));
					Synced = true;
				}
				else
				{
					Synced = false;
					MessageManager.RegisterNamedMessageHandler(GUID + "_OnReceiveConfigSync", new HandleNamedMessageDelegate(OnReceiveSync));
					RequestSync();
				}
			}

			public void RequestSync()
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				if (!IsClient)
				{
					return;
				}
				FastBufferWriter stream = default(FastBufferWriter);
				((FastBufferWriter)(ref stream))..ctor(IntSize, (Allocator)2, -1);
				try
				{
					SendMessage(stream, GUID + "_OnRequestConfigSync", 0uL);
				}
				finally
				{
					((IDisposable)(FastBufferWriter)(ref stream)).Dispose();
				}
			}

			private void OnRequestSync(ulong clientId, FastBufferReader _)
			{
				//IL_003c: 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_0055: Unknown result type (might be due to invalid IL or missing references)
				if (!IsHost)
				{
					return;
				}
				byte[] array = SerializeToBytes(Instance);
				int num = array.Length;
				FastBufferWriter stream = default(FastBufferWriter);
				((FastBufferWriter)(ref stream))..ctor(num + IntSize, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref stream)).WriteValueSafe<int>(ref num, default(ForPrimitives));
					((FastBufferWriter)(ref stream)).WriteBytesSafe(array, -1, 0);
					SendMessage(stream, GUID + "_OnReceiveConfigSync", clientId);
				}
				catch (Exception arg)
				{
					EasySyncPlugin.ConditionLog($"Error occurred syncing config with client: {clientId}\n{arg}", condition: true, (LogLevel)2);
				}
				finally
				{
					((IDisposable)(FastBufferWriter)(ref stream)).Dispose();
				}
			}

			private void OnReceiveSync(ulong _, FastBufferReader reader)
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				if (!((FastBufferReader)(ref reader)).TryBeginRead(IntSize))
				{
					EasySyncPlugin.ConditionLog("Config sync error: Could not begin reading buffer.", condition: true, (LogLevel)2);
					return;
				}
				int num = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
				if (!((FastBufferReader)(ref reader)).TryBeginRead(num))
				{
					EasySyncPlugin.ConditionLog("Config sync error: Host could not sync.", condition: true, (LogLevel)2);
					return;
				}
				byte[] data = new byte[num];
				((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0);
				try
				{
					SyncInstance(data);
				}
				catch (Exception arg)
				{
					EasySyncPlugin.ConditionLog($"Error syncing config instance!\n{arg}", condition: true, (LogLevel)2);
				}
			}
		}

		private static readonly Dictionary<string, SyncedInstanceContainer> instancesToSync = new Dictionary<string, SyncedInstanceContainer>();

		public static SyncedInstanceContainer? RegisterForSyncing(object instance, string GUID)
		{
			if (EasySyncPlugin.ConditionLog("Cannot register a null instance for syncing!", instance == null, (LogLevel)2))
			{
				return null;
			}
			SyncedInstanceContainer value = new SyncedInstanceContainer(instance, GUID);
			if (EasySyncPlugin.ConditionLog($"Could not register instance ({instance}) of type ({instance.GetType().Name}) for syncing! Does it inherit from SyncedInstance from CSync?", !value.isValid, (LogLevel)2))
			{
				return null;
			}
			if (instancesToSync.TryGetValue(GUID, out var _))
			{
				EasySyncPlugin.ConditionLog("An instance with GUID " + GUID + " was already registered!", condition: true, (LogLevel)4);
				return null;
			}
			value.InitInstance();
			instancesToSync.Add(GUID, value);
			return value;
		}

		public static void UnregisterFromSyncing(string GUID)
		{
			if (instancesToSync.ContainsKey(GUID))
			{
				instancesToSync.Remove(GUID);
			}
		}

		internal static void SyncAllInstances()
		{
			foreach (SyncedInstanceContainer value in instancesToSync.Values)
			{
				value.BeginSync();
			}
		}

		internal static void RevertSyncAllInstances()
		{
			foreach (SyncedInstanceContainer value in instancesToSync.Values)
			{
				value.RevertSync();
			}
		}

		private static void SendMessage(FastBufferWriter stream, string label, ulong clientId = 0uL)
		{
			//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)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			NetworkDelivery val = (NetworkDelivery)((((FastBufferWriter)(ref stream)).Capacity > 1300) ? 4 : 2);
			NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(label, clientId, stream, val);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "EasySync";

		public const string PLUGIN_NAME = "EasySync";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}