inkle / ink

inkle's open source scripting language for writing interactive narrative.
http://www.inklestudios.com/ink
MIT License
3.97k stars 482 forks source link

Choice tags are gone after state reloading #857

Open smwhr opened 11 months ago

smwhr commented 11 months ago

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 : https://github.com/y-lohse/inkjs/issues/1022

13xforever commented 11 months ago

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));
        }
    }
Shepard commented 11 months ago

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.)