Decompiled source of TestFilter SlopCrewClient dll 9CF9BF3E v0.0.0

SlopCrewClient.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ProtoBuf;
using ProtoBuf.Meta;
using SlopCrew.API;
using UnityEngine;
using cspotcode.SlopCrewClient.Patches;
using cspotcode.SlopCrewClient.SlopCrewAPI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("SlopCrewClient")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.0.2.0")]
[assembly: AssemblyInformationalVersion("0.0.2+59363cfb92c4b4440dd00a35b6fa9fff5f36ac75")]
[assembly: AssemblyProduct("SlopCrewClient")]
[assembly: AssemblyTitle("SlopCrewClient")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.2.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 cspotcode.SlopCrewClient
{
	public class Client<T>
	{
		public delegate void PacketReceivedHandler(uint playerId, T packet, bool local);

		public const uint LocalPlayerId = 4294967294u;

		private readonly string modName;

		private bool enabled;

		public float MaxAllowedClockDrift = 1f;

		public float MaxClockScaling = 0.05f;

		private bool firstTickReceived;

		private float tickTimeAccumulator;

		private float smoothedTickTimeAccumulator;

		private bool receivedTickRateFromRealServer;

		private ISlopCrewAPI api => APIManager.API;

		public ISlopCrewAPI SlopCrewAPI => APIManager.API;

		public ulong CurrentTickSmoothed { get; private set; }

		public ulong CurrentTick { get; private set; }

		public float TickDuration { get; private set; } = 0.1f;


		public bool Enabled => enabled;

		public bool ApiAvailable => api != null;

		public event PacketReceivedHandler OnPacketReceived;

		static Client()
		{
			RuntimeTypeModel.Default.Add(typeof(Vector3), true, (CompatibilityLevel)0).SetSurrogate(typeof(Vector3Surrogate));
			RuntimeTypeModel.Default.Add(typeof(Vector2), true, (CompatibilityLevel)0).SetSurrogate(typeof(Vector2Surrogate));
		}

		public Client(string modName)
		{
			this.modName = modName;
			APIManager.OnAPIRegistered += onSlopCrewAPIRegistered;
			UpdateEmitter.EnsureInstance().OnUpdate += Update;
		}

		public void Enable()
		{
			if (!enabled)
			{
				enabled = true;
				if (api != null)
				{
					AddListeners();
				}
			}
		}

		public void Disable()
		{
			if (enabled)
			{
				enabled = false;
				if (api != null)
				{
					RemoveListeners();
				}
			}
		}

		public void Send(T packet, bool receiveLocally)
		{
			byte[] data = SerializePacket(packet);
			api?.SendCustomPacket(modName, data);
			if (receiveLocally)
			{
				this.OnPacketReceived?.Invoke(4294967294u, packet, local: true);
			}
		}

		private void AddListeners()
		{
			RemoveListeners();
			api.OnCustomPacketReceived += onSlopCrewCustomPacketReceived;
			api.OnServerTickReceived += onSlopCrewServerTickReceived;
		}

		private void RemoveListeners()
		{
			api.OnCustomPacketReceived -= onSlopCrewCustomPacketReceived;
			api.OnServerTickReceived -= onSlopCrewServerTickReceived;
		}

		private void onSlopCrewAPIRegistered(ISlopCrewAPI _)
		{
			if (enabled)
			{
				AddListeners();
			}
		}

		private void onSlopCrewCustomPacketReceived(uint playerId, string packetName, byte[] data)
		{
			if (packetName == modName)
			{
				T packet = DeserializePacket(data);
				this.OnPacketReceived?.Invoke(playerId, packet, local: false);
			}
		}

		private void onSlopCrewServerTickReceived(ulong tick)
		{
			CurrentTick = tick;
			firstTickReceived = true;
		}

		private static T DeserializePacket(byte[] data)
		{
			using MemoryStream memoryStream = new MemoryStream(data);
			return Serializer.Deserialize<T>((Stream)memoryStream);
		}

		private static byte[] SerializePacket(T packet)
		{
			using MemoryStream memoryStream = new MemoryStream();
			Serializer.Serialize<T>((Stream)memoryStream, packet);
			return memoryStream.ToArray();
		}

		private void Update()
		{
			if (!receivedTickRateFromRealServer && api != null && api.Connected && api.TickRate > 0)
			{
				receivedTickRateFromRealServer = true;
				TickDuration = 1f / (float)api.TickRate;
			}
			float num = 1f;
			bool flag = CurrentTick > CurrentTickSmoothed;
			bool flag2 = CurrentTickSmoothed > CurrentTick;
			ulong num2 = (flag ? (CurrentTick - CurrentTickSmoothed) : (CurrentTickSmoothed - CurrentTick));
			if (TickDuration * (float)num2 > MaxAllowedClockDrift)
			{
				CurrentTickSmoothed = CurrentTick;
			}
			else
			{
				if (flag)
				{
					num = 1f + MaxClockScaling;
				}
				if (flag2)
				{
					num = 1f - MaxClockScaling;
				}
			}
			tickTimeAccumulator += Time.deltaTime;
			while (tickTimeAccumulator > TickDuration)
			{
				tickTimeAccumulator -= TickDuration;
				CurrentTick++;
			}
			smoothedTickTimeAccumulator += Time.deltaTime * num;
			while (smoothedTickTimeAccumulator > TickDuration)
			{
				smoothedTickTimeAccumulator -= TickDuration;
				CurrentTickSmoothed++;
			}
		}
	}
	[BepInPlugin("SlopCrewClient", "SlopCrewClient", "0.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		public Plugin()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)(((BaseUnityPlugin)this).Info.Metadata.Name + " plugin loaded"));
		}

		private void Awake()
		{
			Instance = this;
			CustomAppAPIPatch.AttemptPatch();
			APIManager.Init();
		}
	}
	[ProtoContract]
	public class Vector3Surrogate
	{
		[ProtoMember(1)]
		public readonly float X;

		[ProtoMember(2)]
		public readonly float Y;

		[ProtoMember(3)]
		public readonly float Z;

		public Vector3Surrogate(float x, float y, float z)
		{
			X = x;
			Y = y;
			Z = z;
		}

		public static implicit operator Vector3Surrogate(Vector3 v)
		{
			//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 Vector3Surrogate(v.x, v.y, v.z);
		}

		public static implicit operator Vector3(Vector3Surrogate v)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(v.X, v.Y, v.Z);
		}
	}
	[ProtoContract]
	public class Vector2Surrogate
	{
		[ProtoMember(1)]
		public readonly float X;

		[ProtoMember(2)]
		public readonly float Y;

		public Vector2Surrogate(float x, float y)
		{
			X = x;
			Y = y;
		}

		public static implicit operator Vector2Surrogate(Vector2 v)
		{
			//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 Vector2Surrogate(v.x, v.y);
		}

		public static implicit operator Vector2(Vector2Surrogate v)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(v.X, v.Y);
		}
	}
	internal class UpdateEmitter : MonoBehaviour
	{
		internal static UpdateEmitter Instance { get; private set; }

		public event Action OnUpdate;

		public event Action OnLateUpdate;

		internal static UpdateEmitter EnsureInstance()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if ((Object)(object)Instance == (Object)null)
			{
				GameObject val = new GameObject("SlopCrewClient");
				Object.DontDestroyOnLoad((Object)val);
				Instance = val.AddComponent<UpdateEmitter>();
			}
			return Instance;
		}

		private void Update()
		{
			this.OnUpdate?.Invoke();
		}

		private void LateUpdate()
		{
			this.OnLateUpdate?.Invoke();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "SlopCrewClient";

		public const string PLUGIN_NAME = "SlopCrewClient";

		public const string PLUGIN_VERSION = "0.0.2";
	}
}
namespace cspotcode.SlopCrewClient.SlopCrewAPI
{
	public class APIManager
	{
		private const string SlopCrewGUID = "SlopCrew.Plugin";

		private static bool _CheckedIfSlopCrewInstalled;

		private static bool _IsSlopCrewInstalled;

		public static bool IsSlopCrewInstalled
		{
			get
			{
				if (!_CheckedIfSlopCrewInstalled)
				{
					throw new Exception("SlopCrewClient not initialized yet");
				}
				return _IsSlopCrewInstalled;
			}
		}

		public static ISlopCrewAPI? API { get; private set; }

		public static event Action<ISlopCrewAPI>? OnAPIRegistered;

		internal static void Init()
		{
			_IsSlopCrewInstalled = Chainloader.PluginInfos.Keys.Contains("SlopCrew.Plugin");
			_CheckedIfSlopCrewInstalled = true;
			if (IsSlopCrewInstalled)
			{
				SlopCrew_Init();
			}
		}

		private static void SlopCrew_Init()
		{
			APIManager.OnAPIRegistered += delegate(ISlopCrewAPI api)
			{
				if (API != null)
				{
					throw new Exception("SlopCrew API unexpectedly registered multiple times.");
				}
				API = new SlopCrewAPI(api);
				APIManager.OnAPIRegistered?.Invoke(API);
			};
			if (APIManager.API != null)
			{
				API = new SlopCrewAPI(APIManager.API);
				APIManager.OnAPIRegistered?.Invoke(API);
			}
		}
	}
	public interface ISlopCrewAPI
	{
		string ServerAddress { get; }

		int PlayerCount { get; }

		bool Connected { get; }

		ulong Latency { get; }

		int TickRate { get; }

		int? StageOverride { get; set; }

		uint? PlayerId { get; }

		string? PlayerName { get; }

		ReadOnlyCollection<uint>? Players { get; }

		event Action<int> OnPlayerCountChanged;

		event Action OnConnected;

		event Action OnDisconnected;

		event Action<uint, string, byte[]> OnCustomPacketReceived;

		event Action<uint, string, byte[]> OnCustomCharacterInfoReceived;

		event Action<ulong> OnServerTickReceived;

		string? GetGameObjectPathForPlayerID(uint playerId);

		uint? GetPlayerIDForGameObjectPath(string gameObjectPath);

		bool? PlayerIDExists(uint playerId);

		string? GetPlayerName(uint playerId);

		void SendCustomPacket(string id, byte[] data);

		void SetCustomCharacterInfo(string id, byte[]? data);
	}
	public class SlopCrewAPI : ISlopCrewAPI
	{
		private ISlopCrewAPI api;

		public string ServerAddress => api.ServerAddress;

		public int PlayerCount => api.PlayerCount;

		public bool Connected => api.Connected;

		public ulong Latency => api.Latency;

		public int TickRate => api.TickRate;

		public int? StageOverride
		{
			get
			{
				return api.StageOverride;
			}
			set
			{
				api.StageOverride = value;
			}
		}

		public uint? PlayerId => api.PlayerId;

		public string? PlayerName => api.PlayerName;

		public ReadOnlyCollection<uint>? Players => api.Players;

		public event Action<int> OnPlayerCountChanged
		{
			add
			{
				api.OnPlayerCountChanged += value;
			}
			remove
			{
				api.OnPlayerCountChanged -= value;
			}
		}

		public event Action OnConnected
		{
			add
			{
				api.OnConnected += value;
			}
			remove
			{
				api.OnConnected -= value;
			}
		}

		public event Action OnDisconnected
		{
			add
			{
				api.OnDisconnected += value;
			}
			remove
			{
				api.OnDisconnected -= value;
			}
		}

		public event Action<uint, string, byte[]> OnCustomPacketReceived
		{
			add
			{
				api.OnCustomPacketReceived += value;
			}
			remove
			{
				api.OnCustomPacketReceived -= value;
			}
		}

		public event Action<uint, string, byte[]> OnCustomCharacterInfoReceived
		{
			add
			{
				api.OnCustomCharacterInfoReceived += value;
			}
			remove
			{
				api.OnCustomCharacterInfoReceived -= value;
			}
		}

		public event Action<ulong> OnServerTickReceived
		{
			add
			{
				api.OnServerTickReceived += value;
			}
			remove
			{
				api.OnServerTickReceived -= value;
			}
		}

		internal SlopCrewAPI(ISlopCrewAPI api)
		{
			this.api = api;
		}

		public string? GetGameObjectPathForPlayerID(uint playerId)
		{
			return api.GetGameObjectPathForPlayerID(playerId);
		}

		public uint? GetPlayerIDForGameObjectPath(string gameObjectPath)
		{
			return api.GetPlayerIDForGameObjectPath(gameObjectPath);
		}

		public bool? PlayerIDExists(uint playerId)
		{
			return api.PlayerIDExists(playerId);
		}

		public string? GetPlayerName(uint playerId)
		{
			return api.GetPlayerName(playerId);
		}

		public void SendCustomPacket(string id, byte[] data)
		{
			api.SendCustomPacket(id, data);
		}

		public void SetCustomCharacterInfo(string id, byte[]? data)
		{
			api.SetCustomCharacterInfo(id, data);
		}
	}
}
namespace cspotcode.SlopCrewClient.Patches
{
	[HarmonyPatch]
	internal class CustomAppAPIPatch
	{
		internal static void AttemptPatch()
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			Assembly assembly = (from a in AppDomain.CurrentDomain.GetAssemblies()
				where a.GetName().Name == "CustomAppAPI"
				select a).FirstOrDefault();
			if (assembly == null)
			{
				return;
			}
			Type type = (from t in assembly.GetTypes()
				where t.Name == "CustomAppMod"
				select t).FirstOrDefault();
			if (!(type == null))
			{
				MethodInfo method = type.GetMethod("FindDerivedTypes", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					MethodInfo method2 = typeof(CustomAppAPIPatch).GetMethod("FindDerivedTypes_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
					new Harmony("SlopCrewClient").Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static bool FindDerivedTypes_Prefix(Assembly assembly, Type baseType, ref IEnumerable<Type> __result)
		{
			Type baseType2 = baseType;
			__result = assembly.GetTypes().Where(delegate(Type t)
			{
				try
				{
					return baseType2.IsAssignableFrom(t) && t != baseType2;
				}
				catch (TypeLoadException)
				{
					return false;
				}
			});
			return false;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}