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 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("DesinkDetecter")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DesinkDetecter")]
[assembly: AssemblyTitle("DesinkDetecter")]
[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 = "DesinkDetecter";
public const string PLUGIN_NAME = "DesinkDetecter";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace DesinkDetecter
{
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.David_Loves_JellyCar_Worlds.DesinkDetecter", "DesinkDetecter", "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 = Host.level;
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 DesinkDetecter is loaded!");
Harmony val = new Harmony("com.David_Loves_JellyCar_Worlds.DesinkDetecter");
((BaseUnityPlugin)this).Logger.LogInfo((object)"harmany created");
val.PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"DesinkDetecter 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_0214: Unknown result type (might be due to invalid IL or missing references)
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
//IL_0231: Unknown result type (might be due to invalid IL or missing references)
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
while (!checksumPacketQueue.IsEmpty)
{
if (checksumPacketQueue.TryDequeue(out var result))
{
if (result.level == Host.level)
{
receivedCheckSumPackets.Add(result);
}
else
{
Debug.Log((object)"receved a checksum from a difrent 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 (Host.level == receivedCheckSumPacket2.level && LocalChecksums.ContainsKey(receivedCheckSumPacket2.tick))
{
if (LocalChecksums[receivedCheckSumPacket2.tick] == receivedCheckSumPacket2.checksum)
{
LocalChecksums.Remove(receivedCheckSumPacket2.tick);
list.Remove(receivedCheckSumPacket2);
break;
}
Debug.Log((object)("desinking frame data = " + LocalDebugInfo[receivedCheckSumPacket2.tick]));
Debug.Log((object)$"desink happend on frame {receivedCheckSumPacket2.tick} and the outer players checksum was {receivedCheckSumPacket2.checksum} my checksum was {LocalChecksums[receivedCheckSumPacket2.tick]}");
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!!!!!!!!!!");
}
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);
}
}
}
}