152 lines
4.6 KiB
C#
152 lines
4.6 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Tomlyn;
|
|
using Tomlyn.Model;
|
|
|
|
namespace SessionZero.Data.Sztl;
|
|
|
|
public static class SztlParser
|
|
{
|
|
public static SzTemplate ParseTemplate(string tomlText)
|
|
{
|
|
var doc = Toml.ToModel(tomlText);
|
|
|
|
|
|
if (!doc.ContainsKey("metadata") || doc["metadata"] is not TomlTable metadata)
|
|
{
|
|
throw new Exception("Template missing the [metadata] section");
|
|
}
|
|
|
|
// Determine template type and fill metadata
|
|
string templateType = metadata.TryGetValue("template_type", out var tempTypeVal)
|
|
? tempTypeVal?.ToString() ?? throw new Exception("Template missing template_type metadata")
|
|
: throw new Exception("Template missing template_type metadata");
|
|
|
|
SzTemplate template = templateType switch
|
|
{
|
|
"data" => new SzDataObjectTemplate(),
|
|
_ => throw new NotImplementedException($"Unknown template_type '{templateType}'")
|
|
};
|
|
|
|
if (metadata.TryGetValue("id", out var idVal)) template.Id = idVal?.ToString()!;
|
|
else throw new Exception("Template missing id metadata");
|
|
|
|
if (metadata.TryGetValue("uuid", out var uuidVal)) template.Uuid = uuidVal?.ToString()!;
|
|
else throw new Exception("Template missing uuid metadata");
|
|
|
|
if (metadata.TryGetValue("version", out var versionVal)) template.Version = versionVal?.ToString()!;
|
|
else throw new Exception("Template missing version metadata");
|
|
|
|
if (metadata.TryGetValue("compatible_systems", out var compSysVal) && compSysVal is string[] arr)
|
|
template.CompatibleSystems = arr.ToList();
|
|
|
|
if (metadata.TryGetValue("description", out var descVal))
|
|
template.Description = descVal?.ToString()!;
|
|
else throw new Exception("Template missing description metadata");
|
|
|
|
template.ParseAdditionalMetaData(doc);
|
|
|
|
// Process all other tables as fields or groups
|
|
ProcessTable(template, doc);
|
|
|
|
return template;
|
|
}
|
|
|
|
|
|
|
|
private static void InsertFieldIntoGroup(SzTemplate template, string[] pathParts, TomlTable table)
|
|
{
|
|
var groupDict = template.SubGroups;
|
|
SztlFieldGroup currentGroup = null!;
|
|
|
|
for (int i = 0; i < pathParts.Length - 1; i++)
|
|
{
|
|
var part = pathParts[i];
|
|
|
|
if (!groupDict.TryGetValue(part, out var grp))
|
|
{
|
|
grp = new SztlFieldGroup { Id = part };
|
|
groupDict[part] = grp;
|
|
}
|
|
currentGroup = grp;
|
|
groupDict = grp.SubGroups;
|
|
}
|
|
|
|
var fieldId = pathParts[^1];
|
|
var leafTable = table;
|
|
|
|
if (table.TryGetValue(fieldId, out var possibleLeaf) && possibleLeaf is TomlTable t)
|
|
{
|
|
leafTable = t;
|
|
}
|
|
|
|
var field = ParseFieldFromTable(fieldId, leafTable);
|
|
currentGroup.Fields[fieldId] = field;
|
|
}
|
|
|
|
|
|
private static SztlField ParseFieldFromTable(string id, TomlTable table)
|
|
{
|
|
var field = new SztlField
|
|
{
|
|
Id = id
|
|
};
|
|
|
|
if (!table.TryGetValue("type", out var tVal))
|
|
{
|
|
throw new Exception($"Field '{id}' missing type");
|
|
}
|
|
|
|
var typeStr = tVal?.ToString() ?? throw new Exception($"Field '{id}' has null type");
|
|
if (!Enum.TryParse<SzFieldType>(typeStr, ignoreCase: true, out var ftype))
|
|
{
|
|
throw new Exception($"Field '{id}' has unknown type '{typeStr}'");
|
|
}
|
|
field.Type = ftype;
|
|
|
|
if (table.TryGetValue("default_value", out var dVal))
|
|
{
|
|
field.DefaultValue = dVal;
|
|
}
|
|
|
|
if (ftype == SzFieldType.Textblock)
|
|
{
|
|
field.IsTextBlock = true;
|
|
}
|
|
|
|
return field;
|
|
}
|
|
|
|
private static void ProcessTable(SzTemplate template, TomlTable table, string parentPath = "")
|
|
{
|
|
foreach (var (key, value) in table)
|
|
{
|
|
if (key == "metadata") continue;
|
|
|
|
var path = string.IsNullOrEmpty(parentPath) ? key : $"{parentPath}.{key}";
|
|
|
|
if (value is TomlTable t)
|
|
{
|
|
if (t.ContainsKey("type"))
|
|
{
|
|
var field = ParseFieldFromTable(key, t);
|
|
|
|
if (string.IsNullOrEmpty(parentPath))
|
|
{
|
|
template.Fields[key] = field;
|
|
}
|
|
else
|
|
{
|
|
InsertFieldIntoGroup(template, path.Split('.'), t);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ProcessTable(template, t, path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |