namespace Aeshnidae.MoveGuard;
///
/// Entry point ACE looks for: assembly "Aeshnidae.MoveGuard.dll" -> type
/// "Aeshnidae.MoveGuard.Mod".
///
public class Mod : IHarmonyMod
{
public static readonly string Name = typeof(Mod).Assembly.GetName().Name!;
public static readonly string HarmonyId = $"mod.{Name.ToLowerInvariant()}";
public static readonly string ModPath = Path.Combine(ModManager.ModPath, Name);
public static ModContainer? Container => ModManager.GetModContainerByPath(ModPath);
public static Settings Settings { get; private set; } = new();
/// Counters for /moveguard, so the rule is visible rather than mysterious.
public static long SpeedViolations, GeometryViolations, Rejections, Kicks;
private static Harmony? _harmony;
private bool _disposed;
public void Initialize()
{
try
{
Settings = Settings.Load(ModPath);
_harmony = new Harmony(HarmonyId);
_harmony.PatchAllUncategorized(typeof(Mod).Assembly);
ModManager.Log($"[{Name}] active - mode {Settings.ModeValue}, " +
$"speed tolerance x{Settings.SpeedTolerance:F2} + {Settings.SlackUnits:F1}u, " +
$"catch-up {Settings.MaxCatchUpSeconds:F1}s, " +
$"geometry {(Settings.CheckGeometry ? (Settings.EnforceGeometry ? "enforced" : "logged") : "off")}, " +
$"exempt {Settings.ExemptLevel}+");
}
catch (Exception ex)
{
ModManager.Log($"[{Name}] failed to initialize: {ex}", ModManager.LogLevel.Error);
}
}
/// Re-read Settings.json without a restart. Patches stay in place.
public static void Reload()
{
Settings = Settings.Load(ModPath);
ModManager.Log($"[{Name}] settings reloaded - mode {Settings.ModeValue}");
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_harmony?.UnpatchAll(HarmonyId);
_harmony = null;
Tracker.Clear();
ModManager.Log($"[{Name}] shut down");
}
_disposed = true;
}
}