using Cthangover.Core.Bootstrap;
using Cthangover.Core.Events;
using Cthangover.Core.Mods;
using Cthangover.Core.Scenarios;
using Cthangover.Core.UI;
using Cthangover.Core.Utils;
using Cthangover.Mods.Dialog.Scenarios;
using Godot;
namespace Cthangover.Mods.Dialog
{
///
/// Engine-mod initializer for the dialog subsystem. On resources-ready it
/// publishes the scenario event factory used by the core SceneManager and
/// parks the /root/DialogRunner node implementing the core
/// IInteractiveDialogRunner contract. All operations are idempotent:
/// ModManager.Reload() re-runs OnModResourcesReady, so node
/// creation must tolerate repeat invocations. Scenario command strategies
/// of every mod reach their factory through
/// , not through this initializer.
///
public class DialogModInitializer : IModInitializer
{
private static bool initialized;
/// No per-mod setup is required; registration happens on resources-ready.
public void OnModLoaded(string modId) { }
///
/// Publishes the scenario event factory and queues the dialog runner
/// node. Safe to call again after a mod reload.
///
public void OnModResourcesReady()
{
if (initialized)
return;
initialized = true;
// Scenario-backed events (scene definitions and test-play) are built
// by the core SceneManager through this factory.
AppServices.Current.SceneEvents.ScenarioEventFactory = new ScenarioEventFactory();
EnsureDialogRunner();
}
private static void EnsureDialogRunner()
{
var root = ModEventBus.Instance?.GetTree()?.Root;
if (root == null)
{
GameLogger.Log("DIALOG", "DialogModInitializer: tree root not available, skipping runner setup", LogLevel.Error);
return;
}
if (root.GetNodeOrNull("DialogRunner") != null)
return;
// Deferred: OnModResourcesReady fires while the root is still
// setting up autoload children, so a direct AddChild is rejected.
ModRoot.AddDeferred(new DialogScriptRunner { Name = "DialogRunner" });
}
}
}