Decompiled source of SpeedrunChrono v1.0.2

BepInEx/plugins/speedrunchrono.dll

Decompiled 3 days ago
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Mirror;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using YAPYAP;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("speedrunchrono")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("speedrunchrono")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6cd78860-c1c2-4a61-a3a2-ce05ca1f4adf")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SpeedrunChrono;

public static class ChronoManager
{
	private static readonly Dictionary<int, float> PlayerTimers = new Dictionary<int, float>();

	private static Pawn localPawn;

	private static GameObject chronoCanvasObject;

	private static Canvas chronoCanvas;

	private static TMP_Text localChronoText;

	private static bool chronoStarted = false;

	public static void RegisterPlayer(Pawn pawn)
	{
		if ((Object)(object)pawn == (Object)null)
		{
			return;
		}
		int playerNetId = pawn.PlayerNetId;
		if (playerNetId >= 0)
		{
			if (!PlayerTimers.ContainsKey(playerNetId))
			{
				PlayerTimers[playerNetId] = 0f;
				Debug.Log((object)("[SpeedrunChrono] Nouveau joueur enregistré : " + pawn.PlayerName + " (" + playerNetId + ")"));
			}
			if (((NetworkBehaviour)pawn).isLocalPlayer)
			{
				localPawn = pawn;
				CreateHUD();
				Debug.Log((object)"[SpeedrunChrono] Joueur local enregistré.");
			}
		}
	}

	public static void UnregisterPlayer(Pawn pawn)
	{
		if (!((Object)(object)pawn == (Object)null))
		{
			int playerNetId = pawn.PlayerNetId;
			if (playerNetId >= 0)
			{
				PlayerTimers.Remove(playerNetId);
			}
			if (((NetworkBehaviour)pawn).isLocalPlayer)
			{
				localPawn = null;
				RemoveHUD();
				Debug.Log((object)"[SpeedrunChrono] Joueur local déconnecté.");
			}
		}
	}

	public static void Update()
	{
		//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_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Invalid comparison between Unknown and I4
		if ((Object)(object)localPawn == (Object)null)
		{
			TryFindLocalPawn();
			if ((Object)(object)localPawn == (Object)null)
			{
				return;
			}
		}
		int playerNetId = localPawn.PlayerNetId;
		if (playerNetId < 0)
		{
			return;
		}
		if (!PlayerTimers.ContainsKey(playerNetId))
		{
			PlayerTimers[playerNetId] = 0f;
		}
		if (!chronoStarted && (Object)(object)GameManager.Instance != (Object)null)
		{
			GameState networkcurrentGameState = GameManager.Instance.NetworkcurrentGameState;
			if ((int)networkcurrentGameState == 1)
			{
				chronoStarted = true;
				Debug.Log((object)"[SpeedrunChrono] Première nuit détectée : chrono démarré.");
			}
		}
		if (chronoStarted)
		{
			PlayerTimers[playerNetId] += Time.deltaTime;
		}
		EnsureHUD();
		UpdateHUD();
	}

	private static void TryFindLocalPawn()
	{
		if ((Object)(object)GameManager.Instance == (Object)null)
		{
			return;
		}
		Pawn[] array = Object.FindObjectsByType<Pawn>((FindObjectsSortMode)0);
		foreach (Pawn val in array)
		{
			if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).isLocalPlayer)
			{
				localPawn = val;
				int playerNetId = val.PlayerNetId;
				if (playerNetId >= 0 && !PlayerTimers.ContainsKey(playerNetId))
				{
					PlayerTimers[playerNetId] = 0f;
				}
				CreateHUD();
				Debug.Log((object)("[SpeedrunChrono] Pawn local trouvé automatiquement : " + val.PlayerName));
				break;
			}
		}
	}

	private static void CreateHUD()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Expected O, but got Unknown
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)localChronoText != (Object)null)
		{
			((Component)localChronoText).gameObject.SetActive(true);
			return;
		}
		chronoCanvasObject = new GameObject("SpeedrunChronoCanvas");
		Object.DontDestroyOnLoad((Object)(object)chronoCanvasObject);
		chronoCanvas = chronoCanvasObject.AddComponent<Canvas>();
		chronoCanvas.renderMode = (RenderMode)0;
		chronoCanvas.sortingOrder = 32767;
		CanvasScaler val = chronoCanvasObject.AddComponent<CanvasScaler>();
		val.uiScaleMode = (ScaleMode)1;
		val.referenceResolution = new Vector2(1920f, 1080f);
		val.screenMatchMode = (ScreenMatchMode)0;
		val.matchWidthOrHeight = 0.5f;
		chronoCanvasObject.AddComponent<GraphicRaycaster>();
		GameObject val2 = new GameObject("SpeedrunChronoText");
		val2.transform.SetParent(((Component)chronoCanvas).transform, false);
		localChronoText = (TMP_Text)(object)val2.AddComponent<TextMeshProUGUI>();
		TMP_Text val3 = FindGameFont();
		if ((Object)(object)val3 != (Object)null)
		{
			localChronoText.font = val3.font;
			localChronoText.fontSize = val3.fontSize;
			localChronoText.fontStyle = val3.fontStyle;
			((Graphic)localChronoText).color = ((Graphic)val3).color;
		}
		else
		{
			localChronoText.fontSize = 32f;
			localChronoText.fontStyle = (FontStyles)0;
			((Graphic)localChronoText).color = Color.white;
		}
		localChronoText.alignment = (TextAlignmentOptions)4097;
		((Graphic)localChronoText).raycastTarget = false;
		localChronoText.textWrappingMode = (TextWrappingModes)0;
		localChronoText.overflowMode = (TextOverflowModes)0;
		localChronoText.text = "00:00";
		RectTransform rectTransform = localChronoText.rectTransform;
		rectTransform.anchorMin = new Vector2(0f, 0.5f);
		rectTransform.anchorMax = new Vector2(0f, 0.5f);
		rectTransform.pivot = new Vector2(0f, 0.5f);
		rectTransform.anchoredPosition = new Vector2(30f, 0f);
		rectTransform.sizeDelta = new Vector2(500f, 100f);
		localChronoText.enableAutoSizing = false;
		if (localChronoText.fontSize < 30f)
		{
			localChronoText.fontSize = 30f;
		}
		((Component)localChronoText).gameObject.SetActive(true);
		localChronoText.transform.SetAsLastSibling();
		Canvas.ForceUpdateCanvases();
		Debug.Log((object)"[SpeedrunChrono] HUD créé indépendamment du HUD du jeu.");
	}

	private static TMP_Text FindGameFont()
	{
		TMP_Text[] array = Object.FindObjectsByType<TMP_Text>((FindObjectsSortMode)0);
		TMP_Text[] array2 = array;
		foreach (TMP_Text val in array2)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.font == (Object)null))
			{
				string text = ((Object)((Component)val).gameObject).name.ToLower();
				if (text.Contains("player") || text.Contains("name") || text.Contains("chat") || text.Contains("text"))
				{
					return val;
				}
			}
		}
		TMP_Text[] array3 = array;
		foreach (TMP_Text val2 in array3)
		{
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.font != (Object)null)
			{
				return val2;
			}
		}
		return null;
	}

	private static void EnsureHUD()
	{
		if ((Object)(object)chronoCanvasObject == (Object)null || (Object)(object)chronoCanvas == (Object)null || (Object)(object)localChronoText == (Object)null)
		{
			CreateHUD();
		}
		if ((Object)(object)localChronoText != (Object)null && !((Component)localChronoText).gameObject.activeSelf)
		{
			((Component)localChronoText).gameObject.SetActive(true);
		}
	}

	private static void UpdateHUD()
	{
		if (!((Object)(object)localChronoText == (Object)null) && !((Object)(object)localPawn == (Object)null))
		{
			int playerNetId = localPawn.PlayerNetId;
			if (!PlayerTimers.TryGetValue(playerNetId, out var value))
			{
				value = 0f;
			}
			int num = Mathf.FloorToInt(value);
			int num2 = num / 60;
			int num3 = num % 60;
			localChronoText.text = $"{num2:00}:{num3:00}";
		}
	}

	public static void ResetPlayer(int playerId)
	{
		if (playerId >= 0)
		{
			PlayerTimers[playerId] = 0f;
			Debug.Log((object)("[SpeedrunChrono] Chrono réinitialisé pour le joueur " + playerId));
			UpdateHUD();
		}
	}

	public static void ResetAll()
	{
		PlayerTimers.Clear();
		localPawn = null;
		chronoStarted = false;
		RemoveHUD();
		Debug.Log((object)"[SpeedrunChrono] Tous les chronos ont été réinitialisés.");
	}

	private static void RemoveHUD()
	{
		if ((Object)(object)chronoCanvasObject != (Object)null)
		{
			Object.Destroy((Object)(object)chronoCanvasObject);
		}
		chronoCanvasObject = null;
		chronoCanvas = null;
		localChronoText = null;
	}
}
[BepInPlugin("Xemotal.SpeedrunChrono", "Speedrun Chrono", "1.0.0")]
public class SpeedrunChronoPlugin : BaseUnityPlugin
{
	private Harmony harmony;

	private void Awake()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		harmony = new Harmony("Xemotal.SpeedrunChrono");
		harmony.PatchAll();
		Debug.Log((object)"[SpeedrunChrono] Mod chargé.");
	}

	private void Update()
	{
		ChronoManager.Update();
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		ChronoManager.ResetAll();
	}
}
[HarmonyPatch(typeof(Pawn), "OnStartClient")]
public static class PawnStartClientPatch
{
	[HarmonyPostfix]
	private static void Postfix(Pawn __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			ChronoManager.RegisterPlayer(__instance);
		}
	}
}
[HarmonyPatch(typeof(Pawn), "OnStopClient")]
public static class PawnStopClientPatch
{
	[HarmonyPostfix]
	private static void Postfix(Pawn __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			ChronoManager.UnregisterPlayer(__instance);
		}
	}
}