using System;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("QOLImprovementsCloverpit")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QOLImprovementsCloverpit")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("7647f865-26ed-4efd-8e2c-eff13b732133")]
[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 QOLImprovementsCloverpit;
[BepInPlugin("com.dylan.cloverpit.discordrpc", "Cloverpit Discord RPC", "2.0.1")]
public class QOLImprovementsPlugin : BaseUnityPlugin
{
private const string PluginGUID = "com.dylan.cloverpit.discordrpc";
private const string PluginName = "Cloverpit Discord RPC";
private const string PluginVersion = "2.0.1";
internal static ManualLogSource logger;
private DiscordRpcManager discordManager;
private void Awake()
{
logger = ((BaseUnityPlugin)this).Logger;
discordManager = ((Component)this).gameObject.AddComponent<DiscordRpcManager>();
logger.LogInfo((object)"Cloverpit Discord RPC v2.0.1 loaded!");
}
private void OnDestroy()
{
if ((Object)(object)discordManager != (Object)null)
{
Object.Destroy((Object)(object)discordManager);
}
}
private void OnApplicationQuit()
{
if ((Object)(object)discordManager != (Object)null)
{
discordManager.Shutdown();
}
}
}
public class DiscordRpcManager : MonoBehaviour
{
private const string DISCORD_APP_ID = "1502207417927208980";
private const float UPDATE_INTERVAL = 3f;
private bool initialized = false;
private float lastUpdateTime = 0f;
private long startTimestamp;
private static DiscordRpc.EventHandlers discordEventHandlers = new DiscordRpc.EventHandlers
{
readyCallback = OnReady,
disconnectedCallback = OnDisconnected,
errorCallback = OnError
};
private void Start()
{
try
{
startTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
DiscordRpc.Initialize("1502207417927208980", ref discordEventHandlers, autoRegister: true, null);
initialized = true;
QOLImprovementsPlugin.logger.LogInfo((object)"Discord RPC initialized successfully!");
UpdatePresence();
}
catch (DllNotFoundException)
{
QOLImprovementsPlugin.logger.LogError((object)"====================================");
QOLImprovementsPlugin.logger.LogError((object)"Discord RPC: discord-rpc.dll NOT FOUND!");
QOLImprovementsPlugin.logger.LogError((object)"====================================");
QOLImprovementsPlugin.logger.LogError((object)"Please download discord-rpc.dll from:");
QOLImprovementsPlugin.logger.LogError((object)"https://github.com/discord/discord-rpc/releases");
QOLImprovementsPlugin.logger.LogError((object)"");
QOLImprovementsPlugin.logger.LogError((object)"Extract discord-rpc.dll and place it in:");
QOLImprovementsPlugin.logger.LogError((object)"BepInEx/plugins/discord-rpc.dll");
QOLImprovementsPlugin.logger.LogError((object)"====================================");
}
catch (Exception arg)
{
QOLImprovementsPlugin.logger.LogError((object)$"Failed to initialize Discord RPC: {arg}");
}
}
private void Update()
{
if (initialized)
{
float time = Time.time;
if (time - lastUpdateTime >= 3f)
{
lastUpdateTime = time;
UpdatePresence();
}
DiscordRpc.RunCallbacks();
}
}
private void UpdatePresence()
{
try
{
Type type = AccessTools.TypeByName("GameplayData");
Type type2 = AccessTools.TypeByName("GameplayMaster");
if (type == null || type2 == null)
{
return;
}
object obj = AccessTools.Field(type2, "instance")?.GetValue(null);
if (obj == null)
{
SetPresence("In Menu", "Preparing to gamble", null, null);
return;
}
string numStr = (AccessTools.Method(type, "CoinsGet", (Type[])null, (Type[])null)?.Invoke(null, null))?.ToString() ?? "0";
string numStr2 = (AccessTools.Method(type, "DebtGet", (Type[])null, (Type[])null)?.Invoke(null, null))?.ToString() ?? "0";
string arg = (AccessTools.Method(type, "RoundsLeftToDeadline", (Type[])null, (Type[])null)?.Invoke(null, null))?.ToString() ?? "?";
object obj2 = AccessTools.Method(type, "DebtIndexGet", (Type[])null, (Type[])null)?.Invoke(null, null);
int num = 0;
if (obj2 != null)
{
int result;
if (obj2 is int num2)
{
num = num2;
}
else if (int.TryParse(obj2.ToString(), out result))
{
num = result;
}
}
string state = "\ud83d\udcb0 " + FormatNumber(numStr) + " | \ud83d\udc80 " + FormatNumber(numStr2);
string details = $"Deadline {num + 1} - {arg} rounds left";
SetPresence(details, state, "cloverpit_logo", "Cloverpit");
}
catch (Exception ex)
{
QOLImprovementsPlugin.logger.LogError((object)("Error updating Discord presence: " + ex.GetType().Name + ": " + ex.Message));
QOLImprovementsPlugin.logger.LogError((object)("Stack trace: " + ex.StackTrace));
}
}
private string FormatNumber(string numStr)
{
try
{
if (numStr.Contains("E") || numStr.Contains("e"))
{
if (double.TryParse(numStr, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
{
return result.ToString("0.00E+000", CultureInfo.InvariantCulture);
}
return numStr;
}
if (numStr.Length > 15)
{
string text = numStr.Substring(0, 1);
string text2 = ((numStr.Length > 3) ? numStr.Substring(1, 2) : numStr.Substring(1));
int num = numStr.Length - 1;
double num2 = double.Parse(text + "." + text2);
return $"{num2:F2}E+{num:D3}";
}
if (decimal.TryParse(numStr, NumberStyles.Any, CultureInfo.InvariantCulture, out var result2))
{
if (result2 >= 1000000000m)
{
return ((double)result2).ToString("0.00E+000", CultureInfo.InvariantCulture);
}
if (result2 >= 1000000m)
{
return $"{result2 / 1000000m:F2}M";
}
if (result2 >= 1000m)
{
return $"{result2 / 1000m:F2}K";
}
return ((long)result2).ToString();
}
return numStr;
}
catch
{
return numStr ?? "0";
}
}
private void SetPresence(string details, string state, string largeImageKey, string largeImageText)
{
DiscordRpc.UpdatePresence(default(DiscordRpc.RichPresence), details, state, largeImageKey, largeImageText, startTimestamp);
}
public void Shutdown()
{
if (initialized)
{
DiscordRpc.Shutdown();
initialized = false;
QOLImprovementsPlugin.logger.LogInfo((object)"Discord RPC shutdown");
}
}
private void OnDestroy()
{
Shutdown();
}
private static void OnReady(ref DiscordRpc.DiscordUser user)
{
QOLImprovementsPlugin.logger.LogInfo((object)("Discord RPC connected to user: " + user.username + "#" + user.discriminator));
}
private static void OnDisconnected(int errorCode, string message)
{
QOLImprovementsPlugin.logger.LogWarning((object)$"Discord RPC disconnected: {errorCode} - {message}");
}
private static void OnError(int errorCode, string message)
{
QOLImprovementsPlugin.logger.LogError((object)$"Discord RPC error: {errorCode} - {message}");
}
}
public static class DiscordRpc
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ReadyCallback(ref DiscordUser user);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void DisconnectedCallback(int errorCode, string message);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ErrorCallback(int errorCode, string message);
[Serializable]
public struct EventHandlers
{
public ReadyCallback readyCallback;
public DisconnectedCallback disconnectedCallback;
public ErrorCallback errorCallback;
}
[Serializable]
public struct RichPresence
{
public IntPtr state;
public IntPtr details;
public long startTimestamp;
public long endTimestamp;
public IntPtr largeImageKey;
public IntPtr largeImageText;
public IntPtr smallImageKey;
public IntPtr smallImageText;
public IntPtr partyId;
public int partySize;
public int partyMax;
public IntPtr matchSecret;
public IntPtr joinSecret;
public IntPtr spectateSecret;
public bool instance;
}
[Serializable]
public struct DiscordUser
{
public string userId;
public string username;
public string discriminator;
public string avatar;
}
[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_Initialize")]
public static extern void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId);
[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_Shutdown")]
public static extern void Shutdown();
[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_RunCallbacks")]
public static extern void RunCallbacks();
[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_UpdatePresence")]
private static extern void UpdatePresenceNative(ref RichPresence presence);
public static void UpdatePresence(RichPresence presence, string details = null, string state = null, string largeImageKey = null, string largeImageText = null, long startTimestamp = 0L, string smallImageKey = null, string smallImageText = null)
{
RichPresence richPresence = default(RichPresence);
richPresence.state = ((state != null) ? Marshal.StringToHGlobalAnsi(state) : IntPtr.Zero);
richPresence.details = ((details != null) ? Marshal.StringToHGlobalAnsi(details) : IntPtr.Zero);
richPresence.startTimestamp = startTimestamp;
richPresence.endTimestamp = 0L;
richPresence.largeImageKey = ((largeImageKey != null) ? Marshal.StringToHGlobalAnsi(largeImageKey) : IntPtr.Zero);
richPresence.largeImageText = ((largeImageText != null) ? Marshal.StringToHGlobalAnsi(largeImageText) : IntPtr.Zero);
richPresence.smallImageKey = ((smallImageKey != null) ? Marshal.StringToHGlobalAnsi(smallImageKey) : IntPtr.Zero);
richPresence.smallImageText = ((smallImageText != null) ? Marshal.StringToHGlobalAnsi(smallImageText) : IntPtr.Zero);
richPresence.partyId = IntPtr.Zero;
richPresence.partySize = 0;
richPresence.partyMax = 0;
richPresence.matchSecret = IntPtr.Zero;
richPresence.joinSecret = IntPtr.Zero;
richPresence.spectateSecret = IntPtr.Zero;
richPresence.instance = false;
RichPresence presence2 = richPresence;
UpdatePresenceNative(ref presence2);
if (presence2.state != IntPtr.Zero)
{
Marshal.FreeHGlobal(presence2.state);
}
if (presence2.details != IntPtr.Zero)
{
Marshal.FreeHGlobal(presence2.details);
}
if (presence2.largeImageKey != IntPtr.Zero)
{
Marshal.FreeHGlobal(presence2.largeImageKey);
}
if (presence2.largeImageText != IntPtr.Zero)
{
Marshal.FreeHGlobal(presence2.largeImageText);
}
if (presence2.smallImageKey != IntPtr.Zero)
{
Marshal.FreeHGlobal(presence2.smallImageKey);
}
if (presence2.smallImageText != IntPtr.Zero)
{
Marshal.FreeHGlobal(presence2.smallImageText);
}
}
}