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";
}
}