inkle/ink

Choice tags are gone after state reloading

Opened this issue · 2 comments

smwhr commented

After saving the state at a choice to JSON and then later reloading the story state from that JSON (in a fresh Story object), there are no tags on the choice objects anymore.

To reproduce

Story

Hello, world!
* [Make a choice # just some tag]
- Great choice!

Code

image

Result

image

Expected results

Tag should available on the choice.

More info

Bug was initially detected using inkjs : y-lohse/inkjs#1022

this might require adding <LangVersion>latest</LangVersion> in Tests.csproj, or you can replace raw string with the old multiline verbatim string (@" … ").

    [Test]
    public void InkJs1022Test()
    {
        const string storyContent = """
            Hello, world!
            * [Make a choice # just some tag]
            - Great choice!
            """;

        var story = CompileString(storyContent);
        _ = story.ContinueMaximally();
        var choices = story.currentChoices;
        Console.WriteLine($"Choice text before save: {choices[0].text}");
        Console.WriteLine($"Choice tags before save: [{string.Join(", ", choices[0].tags)}]");
        Assert.That(choices, Is.Not.Null.And.Not.Empty);
        Assert.That(choices[0].tags, Is.Not.Null.And.Not.Empty);

        var stateJson = story.state.ToJson();
        var newStory = CompileString(storyContent);
        newStory.state.LoadJson(stateJson);
        var newChoices = newStory.currentChoices;
        Console.WriteLine($"Choice text after save: {newChoices[0].text}");
        Console.WriteLine($"Choice tags after save: [{(newChoices[0].tags is null? "<null>" : string.Join(", ", newChoices[0].tags))}]");
        Assert.That(newChoices, Is.Not.Null.And.Not.Empty);
        Assert.That(newChoices[0].tags, Is.Not.Null.And.Not.Empty);

        Assert.That(newChoices.Count, Is.EqualTo(choices.Count));
        for (var i = 0; i < choices.Count; i++)
        {
            var oldChoice = choices[i];
            var newChoice = newChoices[i];
            Assert.That(newChoice.text, Is.EqualTo(oldChoice.text));
            Assert.That(newChoice.tags.Count, Is.EqualTo(oldChoice.tags.Count));
            Assert.That(newChoice.tags, Is.EquivalentTo(oldChoice.tags));
            Assert.That(newChoice.targetPath, Is.EqualTo(oldChoice.targetPath));
        }
    }

It looks to me like the reason for this bug is that in JsonSerialisation.cs, the method WriteChoice doesn't write the choice tags to JSON when serialising the state. I was trying to verify this with a simple fix in Ink.js, but the TypeScript compiling doesn't currently work for me.

(The method JObjectToChoice above that also looks like it should deal with tags on choices as well, although that's probably entirely unrelated to this bug.)