Decompiled source of Desink Detecter For MapMaker v1.0.5

DesinkDetecterForMapMaker.dll

Decompiled 2 days ago
using System;
using System.Collections.Concurrent;
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 System.Text;
using BepInEx;
using BoplFixedMath;
using Entwined;
using HarmonyLib;
using MapMaker;
using Microsoft.CodeAnalysis;
using Steamworks.Data;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("DesinkDetecterForMapMaker")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DesinkDetecterForMapMaker")]
[assembly: AssemblyTitle("DesinkDetecterForMapMaker")]
[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 AntiKick
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "DesinkDetecterForMapMaker";

		public const string PLUGIN_NAME = "DesinkDetecterForMapMaker";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace DesinkDetecterForMapMaker
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.David_Loves_JellyCar_Worlds.DesinkDetecterMapMaker", "DesinkDetecterMapMaker", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Host))]
		public class myPatches
		{
			[HarmonyPatch("SendChecksumToPlayer1")]
			[HarmonyPrefix]
			private static bool FuncName_PlugenName_Plug(Host __instance, uint seqNum)
			{
				ulong num = CalculateChecksum();
				if (seqNum == 1)
				{
					LocalChecksums = new Dictionary<uint, ulong>();
					LocalDebugInfo = new Dictionary<uint, string>();
				}
				LocalChecksums.Add(seqNum, num);
				string value = SerializeState();
				LocalDebugInfo.Add(seqNum, value);
				Checksum checksum = default(Checksum);
				checksum.tick = seqNum;
				checksum.checksum = num;
				checksum.level = Plugin.CurrentLevelIdForInputsOnlineThingy;
				ChecksumsChannel.SendMessage(checksum);
				return false;
			}
		}

		[HarmonyPatch(typeof(FixTransform))]
		public class myPatches2
		{
			[HarmonyPatch("Awake")]
			[HarmonyPrefix]
			private static void FuncName_PlugenName_Plug(FixTransform __instance)
			{
				FixTransforms.Add(__instance);
			}
		}

		[HarmonyPatch(typeof(SteamSocket))]
		public class myPatches3
		{
			[HarmonyPatch("OnDisconnected")]
			[HarmonyPrefix]
			private static void FuncName_PlugenName_Plug(SteamSocket __instance, Connection connection, ConnectionInfo data)
			{
				int num = LocalDebugInfo.Count - 1;
				Debug.Log((object)"someone disconented! logging last 5 debug datas.");
				while (num > LocalDebugInfo.Count - 6)
				{
					Debug.Log((object)("debug data for frame " + num));
					Debug.Log((object)("frame data = " + LocalDebugInfo[(uint)num]));
					num--;
				}
			}
		}

		[HarmonyPatch(typeof(SteamManager))]
		public class myPatches4
		{
			[HarmonyPatch("ForceLoadNextLevel")]
			[HarmonyPrefix]
			private static void FuncName_PlugenName_Plug(SteamManager __instance)
			{
				if (LogDebugInfoAtRoundEnd)
				{
					Debug.Log((object)"logging all debug info for this round, get ready for log spam!");
					LogDebugInfoAtRoundEnd = false;
					for (uint num = 1u; num < LocalDebugInfo.Count + 1; num++)
					{
						Debug.Log((object)$"debug data on tick {num} is {LocalDebugInfo[num]}");
					}
					Debug.Log((object)"Log Spam Complete!");
				}
				LocalDebugInfo.Clear();
				RemoveDesyncWarning();
			}
		}

		[HarmonyPatch(typeof(GameSessionHandler))]
		public class myPatches5
		{
			[HarmonyPatch("WinGame")]
			[HarmonyPrefix]
			private static bool FuncName_PlugenName_Plug(GameSessionHandler __instance, int team)
			{
				//IL_0120: Unknown result type (might be due to invalid IL or missing references)
				//IL_0127: Unknown result type (might be due to invalid IL or missing references)
				//IL_012c: Unknown result type (might be due to invalid IL or missing references)
				AudioManager val = AudioManager.Get();
				if ((Object)(object)val != (Object)null)
				{
					val.OnMatchEnded(false);
				}
				__instance.ActivateSuddenDeath(false);
				for (int i = 0; i < PlayerHandler.Get().PlayerList().Count; i++)
				{
					PlayerHandler.Get().PlayerList()[i].IsMostRecentWinner = false;
				}
				if ((Object)(object)textObj == (Object)null)
				{
					for (int j = 0; j < PlayerHandler.Get().PlayerList().Count; j++)
					{
						Player val2 = PlayerHandler.Get().PlayerList()[j];
						if (val2.Team == team)
						{
							val2.WinAGame();
						}
					}
					AchievementHandler.CheckAchievementsOnWinRound();
				}
				AchievementHandler.OnRoundEnded();
				__instance.prepareNextlevel();
				if (!Object.op_Implicit((Object)(object)__instance.winnerTriangle))
				{
					__instance.winnerTriangleCanvas = ((Component)WinnerTriangleCanvas.instance).gameObject;
					__instance.winnerTriangle = ((Component)((Component)WinnerTriangleCanvas.instance.charStatsList).transform.parent).gameObject;
				}
				__instance.playerInitRoutine.Delay(__instance.DelayBeforeNextLevelInput - (Fix)2L);
				__instance.playerInitRoutine.Function((Action)__instance.ActivateWinnerTriangle);
				return false;
			}

			[HarmonyPatch("DeclareGameUndecided")]
			[HarmonyPrefix]
			private static bool FuncName_PlugenName_Plug2(GameSessionHandler __instance, List<Player> playerList)
			{
				//IL_025c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0263: Unknown result type (might be due to invalid IL or missing references)
				//IL_0268: Unknown result type (might be due to invalid IL or missing references)
				AudioManager val = AudioManager.Get();
				if ((Object)(object)val != (Object)null)
				{
					val.OnMatchEnded(true);
				}
				__instance.gameInProgress = false;
				AchievementHandler.OnRoundEnded();
				__instance.ActivateSuddenDeath(false);
				if ((Object)(object)textObj == (Object)null)
				{
					long num = 0L;
					for (int i = 0; i < playerList.Count; i++)
					{
						if (num < playerList[i].TimestampWhenKilled)
						{
							num = playerList[i].TimestampWhenKilled;
						}
					}
					for (int j = 0; j < playerList.Count; j++)
					{
						if (num == playerList[j].TimestampWhenKilled)
						{
							playerList[j].IsMostRecentWinner = true;
						}
						else
						{
							playerList[j].IsMostRecentWinner = false;
						}
					}
					for (int k = 0; k < playerList.Count; k++)
					{
						if (!playerList[k].IsMostRecentWinner)
						{
							continue;
						}
						for (int l = 0; l < playerList.Count; l++)
						{
							if (playerList[k].Team == playerList[l].Team)
							{
								playerList[l].IsMostRecentWinner = true;
							}
						}
					}
					bool flag = true;
					for (int m = 0; m < playerList.Count; m++)
					{
						if (!playerList[m].IsMostRecentWinner)
						{
							flag = false;
						}
					}
					if (flag && PlayerHandler.Get().NumberOfPlayers() == 4)
					{
						AchievementHandler.TryAwardAchievement((AchievementEnum)20);
					}
					for (int n = 0; n < playerList.Count; n++)
					{
						if (playerList[n].IsMostRecentWinner)
						{
							playerList[n].WinAGame();
						}
					}
					AchievementHandler.CheckAchievementsOnWinRound();
				}
				__instance.prepareNextlevel();
				if (!Object.op_Implicit((Object)(object)__instance.winnerTriangle))
				{
					__instance.winnerTriangleCanvas = ((Component)WinnerTriangleCanvas.instance).gameObject;
					__instance.winnerTriangle = ((Component)((Component)WinnerTriangleCanvas.instance.charStatsList).transform.parent).gameObject;
				}
				__instance.playerInitRoutine.Delay(__instance.DelayBeforeNextLevelInput - (Fix)2L);
				__instance.playerInitRoutine.Function((Action)__instance.ActivateWinnerTriangle);
				return false;
			}
		}

		[HarmonyPatch(typeof(CharacterStatsList))]
		public class myPatches6
		{
			[HarmonyPatch("ForceNextLevelImmediately")]
			[HarmonyPrefix]
			private static void FuncName_PlugenName_Plug(CharacterStatsList __instance)
			{
				if (LogDebugInfoAtRoundEnd)
				{
					Debug.Log((object)"logging all debug info for this round, get ready for log spam!");
					LogDebugInfoAtRoundEnd = false;
					for (uint num = 1u; num < LocalDebugInfo.Count + 1; num++)
					{
						Debug.Log((object)$"debug data on tick {num} is {LocalDebugInfo[num]}");
					}
					Debug.Log((object)"Log Spam Complete!");
				}
				LocalDebugInfo.Clear();
				RemoveDesyncWarning();
			}
		}

		public struct Checksum
		{
			public ulong checksum;

			public uint tick;

			public int level;
		}

		public static EntwinedPacketChannel<Checksum> ChecksumsChannel;

		public static Dictionary<uint, ulong> LocalChecksums = new Dictionary<uint, ulong>();

		public static Dictionary<uint, string> LocalDebugInfo = new Dictionary<uint, string>();

		public static List<FixTransform> FixTransforms = new List<FixTransform>();

		public static ConcurrentQueue<Checksum> checksumPacketQueue = new ConcurrentQueue<Checksum>();

		public static List<Checksum> receivedCheckSumPackets = new List<Checksum>();

		public static bool LogDebugInfoAtRoundEnd = false;

		public static Canvas canvas;

		public static GameObject textObj;

		public static TextMeshProUGUI textComp;

		public static RectTransform location;

		public static string currentScene;

		private void Awake()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin DesinkDetecterMapMaker is loaded!");
			Harmony val = new Harmony("com.David_Loves_JellyCar_Worlds.DesinkDetecterMapMaker");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"harmany created");
			val.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"DesinkDetecterMapMaker Patch Compleate!");
			GenericEntwiner<Checksum> val2 = new GenericEntwiner<Checksum>((Func<Checksum, byte[]>)ChecksumToBytes, (Func<byte[], Checksum>)BytesToChecksum);
			ChecksumsChannel = new EntwinedPacketChannel<Checksum>((BaseUnityPlugin)(object)this, (IEntwiner<Checksum>)(object)val2);
			ChecksumsChannel.OnMessage += OnChecksum;
		}

		private void Start()
		{
			SteamManager.instance.checkForDesyncs = true;
		}

		private void Update()
		{
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			while (!checksumPacketQueue.IsEmpty)
			{
				if (checksumPacketQueue.TryDequeue(out var result))
				{
					if (result.level == Plugin.CurrentLevelIdForInputsOnlineThingy)
					{
						receivedCheckSumPackets.Add(result);
					}
					else
					{
						Debug.Log((object)$"receved a checksum from a difrent level. my level is {Plugin.CurrentLevelIdForInputsOnlineThingy} and the packets level is {result.level}");
					}
				}
				else
				{
					Debug.Log((object)"failed to dequeue checksum packet for some reson");
				}
			}
			List<Checksum> list = new List<Checksum>();
			foreach (Checksum receivedCheckSumPacket in receivedCheckSumPackets)
			{
				list.Add(receivedCheckSumPacket);
			}
			int num = 0;
			foreach (Checksum receivedCheckSumPacket2 in receivedCheckSumPackets)
			{
				if (Plugin.CurrentLevelIdForInputsOnlineThingy == receivedCheckSumPacket2.level && LocalChecksums.ContainsKey(receivedCheckSumPacket2.tick))
				{
					if (LocalChecksums[receivedCheckSumPacket2.tick] == receivedCheckSumPacket2.checksum)
					{
						LocalChecksums.Remove(receivedCheckSumPacket2.tick);
						list.Remove(receivedCheckSumPacket2);
						break;
					}
					Debug.Log((object)$"desink happend on frame {receivedCheckSumPacket2.tick} and the outer players checksum was {receivedCheckSumPacket2.checksum} my checksum was {LocalChecksums[receivedCheckSumPacket2.tick]} my level was {Plugin.CurrentLevelIdForInputsOnlineThingy} and the packets level is {receivedCheckSumPacket2.level}");
					LogDebugInfoAtRoundEnd = true;
					Debug.Log((object)"we will log all the debug info after the round ends");
					if ((Object)(object)textObj == (Object)null)
					{
						SpawnDesyncWarning();
					}
					LocalChecksums.Remove(receivedCheckSumPacket2.tick);
					list.Remove(receivedCheckSumPacket2);
					throw new Exception("DESINK DETECTED!!!!!!!!! AHHHHHH!!!!!!!!!!");
				}
				if (Plugin.CurrentLevelIdForInputsOnlineThingy != receivedCheckSumPacket2.level)
				{
					Debug.Log((object)$"receved a checksum from a difrent level. my level is {Plugin.CurrentLevelIdForInputsOnlineThingy} and the packets level is {receivedCheckSumPacket2.level}");
					LocalChecksums.Remove(receivedCheckSumPacket2.tick);
					list.Remove(receivedCheckSumPacket2);
				}
				num++;
			}
			receivedCheckSumPackets = list;
			string text = currentScene;
			Scene activeScene = SceneManager.GetActiveScene();
			if (!(text != ((Scene)(ref activeScene)).name))
			{
				return;
			}
			activeScene = SceneManager.GetActiveScene();
			currentScene = ((Scene)(ref activeScene)).name;
			if (!(currentScene == "MainMenu"))
			{
				return;
			}
			if (LogDebugInfoAtRoundEnd)
			{
				Debug.Log((object)"logging all debug info for this round, get ready for log spam!");
				LogDebugInfoAtRoundEnd = false;
				for (uint num2 = 1u; num2 < LocalDebugInfo.Count + 1; num2++)
				{
					Debug.Log((object)$"debug data on tick {num2} is {LocalDebugInfo[num2]}");
				}
				Debug.Log((object)"Log Spam Complete!");
			}
			LocalDebugInfo.Clear();
			RemoveDesyncWarning();
		}

		public byte[] ChecksumToBytes(Checksum checksum)
		{
			uint tick = checksum.tick;
			byte[] array = new byte[16];
			int num = 0;
			ulong checksum2 = checksum.checksum;
			int level = checksum.level;
			uint num2 = (uint)((ulong)level - 18446744071562067968uL);
			num2 = NetworkTools.SwapBytesIfLittleEndian(num2);
			byte[] bytes = BitConverter.GetBytes(num2);
			array[num++] = bytes[0];
			array[num++] = bytes[1];
			array[num++] = bytes[2];
			array[num++] = bytes[3];
			tick = NetworkTools.SwapBytesIfLittleEndian(tick);
			byte[] bytes2 = BitConverter.GetBytes(tick);
			array[num++] = bytes2[0];
			array[num++] = bytes2[1];
			array[num++] = bytes2[2];
			array[num++] = bytes2[3];
			checksum2 = NetworkTools.SwapBytesIfLittleEndian(checksum2);
			bytes2 = BitConverter.GetBytes(checksum2);
			array[num++] = bytes2[0];
			array[num++] = bytes2[1];
			array[num++] = bytes2[2];
			array[num++] = bytes2[3];
			array[num++] = bytes2[4];
			array[num++] = bytes2[5];
			array[num++] = bytes2[6];
			array[num++] = bytes2[7];
			return array;
		}

		public Checksum BytesToChecksum(byte[] bytes)
		{
			Checksum result = default(Checksum);
			byte[] array = new byte[4];
			byte[] array2 = new byte[8];
			int num = 0;
			array[0] = bytes[num++];
			array[1] = bytes[num++];
			array[2] = bytes[num++];
			array[3] = bytes[num++];
			uint num2 = BitConverter.ToUInt32(array, 0);
			num2 = NetworkTools.SwapBytesIfLittleEndian(num2);
			result.level = (int)(num2 + int.MinValue);
			array[0] = bytes[num++];
			array[1] = bytes[num++];
			array[2] = bytes[num++];
			array[3] = bytes[num++];
			result.tick = BitConverter.ToUInt32(array, 0);
			result.tick = NetworkTools.SwapBytesIfLittleEndian(result.tick);
			array2[0] = bytes[num++];
			array2[1] = bytes[num++];
			array2[2] = bytes[num++];
			array2[3] = bytes[num++];
			array2[4] = bytes[num++];
			array2[5] = bytes[num++];
			array2[6] = bytes[num++];
			array2[7] = bytes[num++];
			result.checksum = BitConverter.ToUInt64(array2, 0);
			result.checksum = NetworkTools.SwapBytesIfLittleEndian(result.checksum);
			return result;
		}

		public static ulong CalculateChecksum()
		{
			//IL_0001: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			Fix val = Fix.Zero;
			List<FixTransform> list = new List<FixTransform>();
			foreach (FixTransform fixTransform in FixTransforms)
			{
				if (!((Object)(object)fixTransform == (Object)null))
				{
					list.Add(fixTransform);
				}
			}
			FixTransforms = list;
			for (int i = 0; i < FixTransforms.Count; i++)
			{
				if (!FixTransforms[i].IsDestroyed)
				{
					val = Fix.SlowAdd(val, FixTransforms[i].ComputeCheckSum());
				}
			}
			return (ulong)val.m_rawValue;
		}

		public static string SerializeState()
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			FixTransform[] array = FixTransforms.ToArray();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("----------------");
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i].IsDestroyed)
				{
					continue;
				}
				MonoUpdatable[] components = ((Component)array[i]).GetComponents<MonoUpdatable>();
				if (components != null)
				{
					stringBuilder.Append(((Object)((Component)array[i]).gameObject).name + " hierarchyNumbers = ");
					for (int j = 0; j < components.Length; j++)
					{
						if (components[j].IsDestroyed)
						{
							stringBuilder.Append("[DESTROYED]");
						}
						stringBuilder.Append(components[j].HierarchyNumber);
						stringBuilder.Append(", ");
					}
				}
				else
				{
					stringBuilder.Append(((Object)((Component)array[i]).gameObject).name);
				}
				stringBuilder.Append("\n");
				stringBuilder.Append("posX = ");
				stringBuilder.Append(array[i].position.x);
				stringBuilder.Append(", posY = ");
				stringBuilder.Append(array[i].position.y);
				stringBuilder.Append(", rotation = ");
				stringBuilder.Append(array[i].rotation);
				stringBuilder.AppendLine("----------------");
			}
			return stringBuilder.ToString();
		}

		public void OnChecksum(Checksum checksumPacket, PacketSourceInfo sourceInfo)
		{
			checksumPacketQueue.Enqueue(checksumPacket);
		}

		public static void SpawnDesyncWarning()
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)textObj == (Object)null))
			{
				return;
			}
			if ((Object)(object)canvas == (Object)null)
			{
				GameObject val = GameObject.Find("AbilitySelectCanvas");
				if ((Object)(object)val != (Object)null)
				{
					canvas = val.GetComponent<Canvas>();
				}
				if ((Object)(object)canvas == (Object)null)
				{
					Debug.LogError((object)$"No suitable canvas! Canvas: {canvas}, Scene: {currentScene}");
					return;
				}
			}
			textObj = new GameObject("Desync warning", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			textObj.transform.SetParent(((Component)canvas).transform);
			textComp = textObj.GetComponent<TextMeshProUGUI>();
			((Graphic)textComp).raycastTarget = false;
			((Graphic)textComp).color = Color.red;
			((TMP_Text)textComp).fontSize = 25f;
			((TMP_Text)textComp).alignment = (TextAlignmentOptions)514;
			((TMP_Text)textComp).font = LocalizedText.localizationTable.GetFont(Settings.Get().Language, false);
			location = textObj.GetComponent<RectTransform>();
			location.pivot = new Vector2(0f, 1f);
			location.anchoredPosition = new Vector2(-250f, 650f);
			location.sizeDelta = new Vector2(400f, 50f);
			textObj.SetActive(true);
			((TMP_Text)textComp).text = "Desync Detected! winner will not count this round, game may frezze for a second when going to the next round due to log spamming.";
		}

		public static void RemoveDesyncWarning()
		{
			if ((Object)(object)textObj != (Object)null)
			{
				Object.Destroy((Object)(object)textObj);
			}
		}
	}
}