b451f83174
Captures the pre-Godot-port state of the codebase. This is the rollback anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md). All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
83 lines
2.8 KiB
C#
83 lines
2.8 KiB
C#
using Theriapolis.Core;
|
|
using Theriapolis.Core.Persistence;
|
|
using Theriapolis.Core.Rules.Quests;
|
|
using Xunit;
|
|
|
|
namespace Theriapolis.Tests.Quests;
|
|
|
|
/// <summary>
|
|
/// Phase 6 M4 — capture/restore round-trip for quest engine state.
|
|
/// </summary>
|
|
public sealed class QuestSnapshotTests
|
|
{
|
|
[Fact]
|
|
public void CaptureAndRestore_RoundTripActiveAndCompleted()
|
|
{
|
|
var engine = new QuestEngine();
|
|
engine.AdoptActive(new QuestState
|
|
{
|
|
QuestId = "q1", CurrentStep = "step_a", Status = QuestStatus.Active,
|
|
StartedAt = 100, StepStartedAt = 150,
|
|
});
|
|
engine.Get("q1")!.Journal.Add("started q1");
|
|
engine.AdoptCompleted(new QuestState
|
|
{
|
|
QuestId = "q2", CurrentStep = "<end>", Status = QuestStatus.Completed,
|
|
StartedAt = 0, StepStartedAt = 200,
|
|
});
|
|
engine.Journal.Add("global event 1");
|
|
|
|
var snap = QuestCodec.Capture(engine);
|
|
Assert.Single(snap.Active);
|
|
Assert.Single(snap.Completed);
|
|
Assert.Single(snap.Journal);
|
|
|
|
var rebuilt = new QuestEngine();
|
|
QuestCodec.Restore(rebuilt, snap);
|
|
Assert.True(rebuilt.IsActive("q1"));
|
|
Assert.True(rebuilt.IsCompleted("q2"));
|
|
Assert.Single(rebuilt.Journal);
|
|
Assert.Equal("step_a", rebuilt.Get("q1")!.CurrentStep);
|
|
Assert.Contains("started q1", rebuilt.Get("q1")!.Journal);
|
|
}
|
|
|
|
[Fact]
|
|
public void SaveCodec_RoundTripsQuestEngineState()
|
|
{
|
|
var engine = new QuestEngine();
|
|
engine.AdoptActive(new QuestState
|
|
{
|
|
QuestId = "main_act_i_001_arrival",
|
|
CurrentStep = "find_magistrate",
|
|
Status = QuestStatus.Active,
|
|
StartedAt = 500, StepStartedAt = 700,
|
|
});
|
|
engine.Journal.Add("Arrived in Millhaven");
|
|
|
|
var body = new SaveBody();
|
|
body.Player.Name = "Tester";
|
|
body.QuestEngineState = QuestCodec.Capture(engine);
|
|
|
|
var header = new SaveHeader { Version = C.SAVE_SCHEMA_VERSION, WorldSeedHex = "0xCAFE" };
|
|
var bytes = SaveCodec.Serialize(header, body);
|
|
var (h2, b2) = SaveCodec.Deserialize(bytes);
|
|
|
|
Assert.Equal(C.SAVE_SCHEMA_VERSION, h2.Version);
|
|
Assert.Single(b2.QuestEngineState.Active);
|
|
Assert.Equal("find_magistrate", b2.QuestEngineState.Active[0].CurrentStep);
|
|
Assert.Single(b2.QuestEngineState.Journal);
|
|
}
|
|
|
|
[Fact]
|
|
public void EmptyEngineState_OmitsTagFromSave()
|
|
{
|
|
// No active/completed/journal → no TAG_QUESTS section written.
|
|
var body = new SaveBody { Player = { Name = "Empty" } };
|
|
var bytes = SaveCodec.Serialize(new SaveHeader(), body);
|
|
var (_, b2) = SaveCodec.Deserialize(bytes);
|
|
Assert.Empty(b2.QuestEngineState.Active);
|
|
Assert.Empty(b2.QuestEngineState.Completed);
|
|
Assert.Empty(b2.QuestEngineState.Journal);
|
|
}
|
|
}
|