KSP-RO / ContractConfigurator

A config file based solution for creating new contracts for Kerbal Space Program.
https://forum.kerbalspaceprogram.com/index.php?/topic/91625-1
Other
8 stars 10 forks source link

Exception when storing a List<string> in the PersistentDataStore #6

Open rkunze opened 1 year ago

rkunze commented 1 year ago

Environment: Clean KSP 1.12.4 install with only ModuleManager and ContractConfigurator

Minimal contract type that reproduces the bug:

CONTRACT_TYPE {
    name = PersistentDataStoreBug
    title = "Trigger an Exception in the PersistentDataStore"
    description = "Build and launch any vessel. The exception is triggered after completing the contract and switching back to the space center scene."
    prestige = Trivial
    synopsis = Just testing.
    completedMessage = "Quicksave now and look at quicksafe.sfs to see the broken entry in the persistent data store."
    PARAMETER {
        type = NewVessel
    }

    BEHAVIOUR {
        type = Expression
        CONTRACT_COMPLETED_SUCCESS {
            type = List<string>
            brokenEntry = [ "any string will do to break it" ]
        }
    }
}

Steps to reproduce:

This will trigger the following exception after changing back to the space center:

Exception occured while loading ScenarioModule 'PersistentDataStore':
System.Exception: Error parsing statement.
Error occurred near '*':
[ any string will do to break it ]
..................................* <-- HERE ---> System.ArgumentException: Expected ',' or ']', got end of statement.
  at ContractConfigurator.ExpressionParser.ExpressionParser`1[T].ParseList[TResult] () [0x00167] in <acee7c1cecb143188a2b003e7f2fafc9>:0 
  at ContractConfigurator.ExpressionParser.ListExpressionParser`1[T].ParseList[TResult] () [0x00007] in <acee7c1cecb143188a2b003e7f2fafc9>:0 
  at ContractConfigurator.ExpressionParser.ExpressionParser`1[T].ParseSimpleStatement[TResult] () [0x0037e] in <acee7c1cecb143188a2b003e7f2fafc9>:0 
  at ContractConfigurator.ExpressionParser.ExpressionParser`1[T].ParseStatementInner[TResult] () [0x0005c] in <acee7c1cecb143188a2b003e7f2fafc9>:0 
  at ContractConfigurator.ExpressionParser.ExpressionParser`1[T].ParseStatement[TResult] () [0x000f3] in <acee7c1cecb143188a2b003e7f2fafc9>:0 
  at ContractConfigurator.ExpressionParser.ExpressionParser`1[T].ParseExpression (System.String key, System.String expression, ContractConfigurator.ExpressionParser.DataNode dataNode) [0x00026] in <acee7c1cecb143188a2b003e7f2fafc9>:0 
--- End of inner exception stack trace ---
  at ContractConfigurator.ExpressionParser.ExpressionParser`1[T].ParseExpression (System.String key, System.String expression, ContractConfigurator.ExpressionParser.DataNode dataNode) [0x00089] in <acee7c1cecb143188a2b003e7f2fafc9>:0 
  at ContractConfigurator.ExpressionParser.ExpressionParser`1[T].ParseExpressionGeneric (System.String key, System.String expression, ContractConfigurator.ExpressionParser.DataNode dataNode) [0x00000] in <acee7c1cecb143188a2b003e7f2fafc9>:0 
  at ContractConfigurator.PersistentDataStore.OnLoad (ConfigNode node) [0x000e0] in <acee7c1cecb143188a2b003e7f2fafc9>:0 
rkunze commented 1 year ago

I did a bit of preliminary analysis on this, and the underlying issue seems to be a general problem when parsing a List<string>. This seems to only work for quoted strings or when referencing values with the "@"-Syntax, but breaks down completely for unquoted strings:

And List gets stored in the PersistentDataStore without quoting the contents, as seen in this snippet from quicksafe.sfs from the example game above:

SCENARIO
{
        name = PersistentDataStore
        scene = 7, 8, 5
        DATA
        {
                brokenEntry = List<String>:[ any string will do to break it ]
        }
}
rkunze commented 1 year ago

As a side note, parsing an empty list from [] seems to be broken for any List type.