using BepInEx;
using BepInEx.Unity.IL2CPP;
using BepInEx.Logging;
using HarmonyLib;
using MiraAPI.PluginLoading;
using Reactor;
using System;
using System.Reflection;
namespace TownOfUsStatsExporter;
///
/// Main BepInEx plugin for TownOfUs Stats Exporter.
/// This is a standalone plugin that uses reflection to access TOU Mira data
/// and exports game statistics to a cloud API.
///
[BepInPlugin(PluginGuid, PluginName, PluginVersion)]
[BepInDependency("auavengers.tou.mira", BepInDependency.DependencyFlags.HardDependency)]
[BepInDependency(ReactorPlugin.Id, BepInDependency.DependencyFlags.HardDependency)]
public class TownOfUsStatsPlugin : BasePlugin
{
///
/// Plugin GUID for BepInEx identification.
///
public const string PluginGuid = "com.townofus.stats.exporter";
///
/// Plugin display name.
///
public const string PluginName = "TownOfUs Stats Exporter";
///
/// Plugin version.
///
public const string PluginVersion = "1.0.1";
///
/// Logger instance for the plugin.
///
internal static ManualLogSource Logger { get; private set; } = null!;
///
/// Harmony instance for patching.
///
internal static Harmony Harmony { get; private set; } = null!;
private TownOfUsStatsExporter.Reflection.TouMiraReflectionBridge? reflectionBridge;
///
/// Called when the plugin is loaded by BepInEx.
///
public override void Load()
{
Logger = Log;
Harmony = new Harmony(PluginGuid);
Logger.LogInfo("========================================");
Logger.LogInfo($"{PluginName} v{PluginVersion}");
Logger.LogInfo("========================================");
// Initialize reflection bridge
reflectionBridge = new TownOfUsStatsExporter.Reflection.TouMiraReflectionBridge();
if (!reflectionBridge.Initialize())
{
Logger.LogError("Failed to initialize TOU Mira reflection bridge!");
Logger.LogError("This plugin may not be compatible with your TOU Mira version.");
Logger.LogError("Plugin will be disabled.");
return;
}
Logger.LogInfo($"Successfully connected to TOU Mira v{reflectionBridge.TouMiraVersion}");
Logger.LogInfo($"Compatibility: {reflectionBridge.CompatibilityStatus}");
// Store bridge in static context for patches
ReflectionBridgeProvider.SetBridge(reflectionBridge);
// Apply Harmony patches
try
{
Harmony.PatchAll(Assembly.GetExecutingAssembly());
Logger.LogInfo("Harmony patches applied successfully");
}
catch (Exception ex)
{
Logger.LogError($"Failed to apply Harmony patches: {ex}");
return;
}
Logger.LogInfo($"{PluginName} loaded successfully!");
Logger.LogInfo("Stats will be exported at the end of each game.");
}
///
/// Called when the plugin is unloaded.
///
/// True if unloading was successful.
public override bool Unload()
{
Logger.LogInfo($"Unloading {PluginName}...");
Harmony?.UnpatchSelf();
return true;
}
}
///
/// Static provider for accessing reflection bridge from patches.
///
internal static class ReflectionBridgeProvider
{
private static TownOfUsStatsExporter.Reflection.TouMiraReflectionBridge? bridge;
///
/// Sets the reflection bridge instance.
///
/// The bridge instance.
public static void SetBridge(TownOfUsStatsExporter.Reflection.TouMiraReflectionBridge b) => bridge = b;
///
/// Gets the reflection bridge instance.
///
/// The bridge instance.
/// Thrown if bridge is not initialized.
public static TownOfUsStatsExporter.Reflection.TouMiraReflectionBridge GetBridge() =>
bridge ?? throw new InvalidOperationException("Bridge not initialized");
}