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