-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/main' into docs-update
- Loading branch information
Showing
18 changed files
with
3,540 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
199 changes: 199 additions & 0 deletions
199
src/Games/NexusMods.Games.Larian/BaldursGate3/Utils/PakParsing/ModsettingsFileFormat.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
using System.Text; | ||
using System.Xml; | ||
|
||
namespace NexusMods.Games.Larian.BaldursGate3.Utils.PakParsing; | ||
|
||
/// <summary> | ||
/// Class to parse and write the `modsettings.lsx` xml file format used for the BG3 Load Order. | ||
/// </summary> | ||
public static class ModsettingsFileFormat | ||
{ | ||
public static string SerializeModsettingsLoadOrder(LsxXmlFormat.ModuleShortDesc[] moduleShortDescs) | ||
{ | ||
var settings = new XmlWriterSettings | ||
{ | ||
Indent = true, | ||
OmitXmlDeclaration = false, | ||
}; | ||
|
||
using var stringWriter = new StringWriter(); | ||
using (var xmlWriter = XmlWriter.Create(stringWriter, settings)) | ||
{ | ||
xmlWriter.WriteStartDocument(); | ||
xmlWriter.WriteStartElement("save"); | ||
|
||
WriteVersion(xmlWriter); | ||
WriteRegion(xmlWriter, moduleShortDescs); | ||
|
||
xmlWriter.WriteEndElement(); // save | ||
xmlWriter.WriteEndDocument(); | ||
} | ||
|
||
return stringWriter.ToString(); | ||
} | ||
|
||
public static LsxXmlFormat.ModuleShortDesc[] DeserializeModsettingsLoadOrder(string modsettingsXml) | ||
{ | ||
var modulesLoadOrder = new List<LsxXmlFormat.ModuleShortDesc>(); | ||
var skipFirstGustavDev = true; | ||
|
||
using (var stringReader = new StringReader(modsettingsXml)) | ||
using (var xmlReader = XmlReader.Create(stringReader)) | ||
{ | ||
while (xmlReader.Read()) | ||
{ | ||
if (xmlReader is not { NodeType: XmlNodeType.Element, Name: "node" } || | ||
xmlReader.GetAttribute("id") != "ModuleShortDesc") | ||
{ | ||
continue; | ||
} | ||
|
||
var moduleShortDesc = new LsxXmlFormat.ModuleShortDesc(); | ||
|
||
while (xmlReader.Read() && xmlReader is not { NodeType: XmlNodeType.EndElement, Name: "node" }) | ||
{ | ||
if (xmlReader is { NodeType: XmlNodeType.Element, Name: "attribute" }) | ||
{ | ||
var id = xmlReader.GetAttribute("id"); | ||
var value = xmlReader.GetAttribute("value"); | ||
|
||
switch (id) | ||
{ | ||
case "Folder": | ||
moduleShortDesc.Folder = value ?? string.Empty; | ||
break; | ||
case "MD5": | ||
moduleShortDesc.Md5 = value ?? string.Empty; | ||
break; | ||
case "Name": | ||
moduleShortDesc.Name = value ?? string.Empty; | ||
break; | ||
case "PublishHandle": | ||
moduleShortDesc.PublishHandle = value ?? string.Empty; | ||
break; | ||
case "UUID": | ||
moduleShortDesc.Uuid = value ?? string.Empty; | ||
break; | ||
case "Version64": | ||
moduleShortDesc.Version = value ?? string.Empty; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
// Skip the GustavDev entry | ||
if (skipFirstGustavDev && moduleShortDesc is { Name: "GustavDev" }) | ||
{ | ||
skipFirstGustavDev = false; | ||
continue; | ||
} | ||
|
||
modulesLoadOrder.Add(moduleShortDesc); | ||
} | ||
} | ||
|
||
return modulesLoadOrder.ToArray(); | ||
} | ||
|
||
#region private methods | ||
|
||
private static void WriteVersion(XmlWriter xmlWriter) | ||
{ | ||
xmlWriter.WriteStartElement("version"); | ||
xmlWriter.WriteAttributeString("major", "4"); | ||
xmlWriter.WriteAttributeString("minor", "7"); | ||
xmlWriter.WriteAttributeString("revision", "1"); | ||
xmlWriter.WriteAttributeString("build", "200"); | ||
xmlWriter.WriteEndElement(); | ||
} | ||
|
||
private static void WriteRegion(XmlWriter xmlWriter, LsxXmlFormat.ModuleShortDesc[] moduleShortDescs) | ||
{ | ||
xmlWriter.WriteStartElement("region"); | ||
xmlWriter.WriteAttributeString("id", "ModuleSettings"); | ||
|
||
xmlWriter.WriteStartElement("node"); | ||
xmlWriter.WriteAttributeString("id", "root"); | ||
|
||
xmlWriter.WriteStartElement("children"); | ||
xmlWriter.WriteStartElement("node"); | ||
xmlWriter.WriteAttributeString("id", "Mods"); | ||
|
||
xmlWriter.WriteStartElement("children"); | ||
|
||
// Add default GustavDev entry | ||
WriteModuleShortDesc(xmlWriter, | ||
new LsxXmlFormat.ModuleShortDesc | ||
{ | ||
Folder = "GustavDev", | ||
Name = "GustavDev", | ||
PublishHandle = "0", | ||
Version = "36028797018963968", | ||
Uuid = "28ac9ce2-2aba-8cda-b3b5-6e922f71b6b8", | ||
Md5 = "" | ||
} | ||
); | ||
|
||
// Add pak mod entries | ||
foreach (var moduleShortDesc in moduleShortDescs) | ||
{ | ||
WriteModuleShortDesc(xmlWriter, moduleShortDesc); | ||
} | ||
|
||
xmlWriter.WriteEndElement(); // children | ||
xmlWriter.WriteEndElement(); // node Mods | ||
xmlWriter.WriteEndElement(); // children | ||
xmlWriter.WriteEndElement(); // node root | ||
xmlWriter.WriteEndElement(); // region | ||
} | ||
|
||
internal static void WriteModuleShortDesc(XmlWriter xmlWriter, LsxXmlFormat.ModuleShortDesc moduleShortDesc) | ||
{ | ||
xmlWriter.WriteStartElement("node"); | ||
xmlWriter.WriteAttributeString("id", "ModuleShortDesc"); | ||
|
||
WriteAttribute(xmlWriter, | ||
"Folder", | ||
"LSString", | ||
moduleShortDesc.Folder | ||
); | ||
WriteAttribute(xmlWriter, | ||
"MD5", | ||
"LSString", | ||
moduleShortDesc.Md5 | ||
); | ||
WriteAttribute(xmlWriter, | ||
"Name", | ||
"LSString", | ||
moduleShortDesc.Name | ||
); | ||
WriteAttribute(xmlWriter, | ||
"PublishHandle", | ||
"uint64", | ||
moduleShortDesc.PublishHandle | ||
); | ||
WriteAttribute(xmlWriter, | ||
"UUID", | ||
"guid", | ||
moduleShortDesc.Uuid | ||
); | ||
WriteAttribute(xmlWriter, | ||
"Version64", | ||
"int64", | ||
moduleShortDesc.Version | ||
); | ||
|
||
xmlWriter.WriteEndElement(); | ||
} | ||
|
||
private static void WriteAttribute(XmlWriter xmlWriter, string id, string type, string value) | ||
{ | ||
xmlWriter.WriteStartElement("attribute"); | ||
xmlWriter.WriteAttributeString("id", id); | ||
xmlWriter.WriteAttributeString("type", type); | ||
xmlWriter.WriteAttributeString("value", value); | ||
xmlWriter.WriteEndElement(); | ||
} | ||
|
||
#endregion private methods | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Styles xmlns="https://github.com/avaloniaui" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:controls="using:NexusMods.App.UI.Controls" | ||
xmlns:icons="clr-namespace:NexusMods.Icons;assembly=NexusMods.Icons" | ||
> | ||
|
||
<Design.PreviewWith> | ||
<Border Padding="8"> | ||
<StackPanel Spacing="10"> | ||
<controls:StandardButton /> | ||
</StackPanel> | ||
</Border> | ||
</Design.PreviewWith> | ||
|
||
<!-- Control theme is located at src/Themes/NexusMods.Themes.NexusFluentDark/Resources/ControlThemes/StandardButtonControlTheme.axaml | ||
Default style is found there as well as the default template --> | ||
|
||
</Styles> |
Oops, something went wrong.