namespace Aeshnidae.DevKit;
///
/// Entry point ACE looks for.
///
/// ModContainer resolves the type purely by convention:
/// assembly "Aeshnidae.DevKit.dll" -> type "Aeshnidae.DevKit.Mod"
/// so this class must be named Mod and live in a namespace matching the
/// assembly name. Renaming one without the other is the most common reason a mod
/// loads its assembly and then logs "Missing IHarmonyMod Type".
///
public class Mod : IHarmonyMod
{
///
/// "Aeshnidae.DevKit". Taken from the assembly rather than written out, so a
/// rename cannot leave a stale literal behind.
/// (Note: nameof(Aeshnidae.DevKit) would yield just "Template" - nameof on a
/// namespace returns only its last segment.)
///
public static readonly string Name = typeof(Mod).Assembly.GetName().Name!;
/// Folder this mod was loaded from, e.g. C:\ACEPublic\Mods\Aeshnidae.DevKit
public static readonly string ModPath = Path.Combine(ModManager.ModPath, Name);
public static ModContainer? Container => ModManager.GetModContainerByPath(ModPath);
/// Live settings, re-read every time the mod is enabled.
public static Settings Settings { get; private set; } = new();
private bool _disposed;
///
/// Called by ModContainer.Enable() once the assembly is loaded.
/// The world is not open yet at this point, so keep this cheap and defensive -
/// anything that throws leaves the mod stuck Inactive.
///
public void Initialize()
{
Settings = Settings.Load(ModPath);
// No Harmony patches: this mod is commands only. It reads ACE's caches and the
// world database, and writes to the database only through /wimport, and only
// when Settings.AllowImport says this is a server where that is allowed.
try
{
Db.Initialize();
}
catch (Exception ex)
{
// Not fatal: /winfo and /wexport work from ACE's own cache. Only the
// diff/submit commands need the raw connection, and they report this.
ModManager.Log($"[{Name}] world database connection not available: {ex.Message}", ModManager.LogLevel.Warn);
}
ModManager.Log($"[{Name}] initialized from {ModPath} - {(Settings.AllowImport ? "imports ALLOWED" : "imports off")}, " +
$"base schema {(Settings.HasBase ? Settings.BaseSchema : "(none)")}, label '{Settings.Label}'");
}
///
/// Called by ModContainer.Disable() on shutdown, hot-reload, and /mod disable.
/// Nothing was patched, so there is nothing to unpatch; the caches are dropped so
/// the old assembly can be collected.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
Exporter.Reset();
Names.Reset();
ModManager.Log($"[{Name}] shut down");
}
_disposed = true;
}
}