Mutagen-Modding / Spriggit

A tool to facilitate converting Bethesda plugin files to a text based format that can be stored in Git
GNU General Public License v3.0
93 stars 11 forks source link

Spriggit

A tool to facilitate converting Bethesda plugin files to a text based format that can be stored in Git. Large scale projects can then live in Github, and accept Pull Requests from many developers.

The goal is to help modders store their files in a versioning system that allows them to easily iterate in the same way that programmers do with their code.

Spriggit Demo

Check out the Documentation Official Documentation for more detailed explainations of Spriggit, and more typical use cases and examples.

Reasons to Use Git for Mods

Git is an extremely powerful versioning and iteration tool that almost all programmers use when working. It's what powers the world of coding to be able to iterate new code quickly and collaborate easily.

Some things Git can help you do when developing your mod:

The Workflow:

An Individual Modder

Many Collaborators

Other modders, whether on your team or just helpful people out in the world can help collaborate and participate in your mod's development.

Example Output

Record Data is Stored as Plaintext

Json or Yaml formatting is currently supported.

Here is a snippet of what a record file might look like if Yaml output is used:

FormKey: 087835:Skyrim.esm
EditorID: JewelryNecklaceGoldGems
ObjectBounds:
  First: -3, -9, 0
  Second: 3, 9, 1
Name: Gold Jeweled Necklace
WorldModel:
  Male:
    Model:
      File: Armor\AmuletsandRings\GoldAmuletGemsGO.nif
      Data: 0x020000000300000000000000A4E51E5364647300D8C674AFC031228D64647300D8C674AFB8EC307B64647300262C333B
PickUpSound: 08AB15:Immersive Sounds - Compendium.esp
PutDownSound: 08AB16:Immersive Sounds - Compendium.esp
Race: 013749:Skyrim.esm
Keywords:
- 06BBE9:Skyrim.esm
- 08F95A:Skyrim.esm
- 0A8664:Skyrim.esm
- 10CD0A:Skyrim.esm
Armature:
- 09171F:Skyrim.esm
Value: 485
Weight: 0.5

This file is more palatable to Git and can support diff tools and similar functionality.

Mods are Split into Folders

Rather than having one large file of all of a mod's data, Spriggit splits a mod into a folder of Yaml/Json files.

A typical mod folder structure might look like:

Some/Folder/
   RecordData.yaml          -  The mod header
   Weapons/                 -  Folder for all the weapons
      GlassDagger.yaml      -  File dedicated to the record Glass Dagger
      IronLongsword.yaml    -  Seperate file for the Iron Longsword
   Npcs/                    -  Folder for all the weapons
      Goblin.yaml           -  File dedicated to the Goblin's data

This folder structure helps organize git diffs to be more meaningful. If a new record is added, then this will be seen as a new file. If a record is modified, it will be a modified file. Similar to wanting to avoid having a program's code be in one large monolith file, having smaller bite sized files helps navigate and digest changes being made.

Installation

Spriggit UI

This is a self-contained WPF application, which can only run on Windows. You can add links between a mod file and where it should be translated to, and then sync back and forth with one click.

image image

Spriggit CLI

Spriggit comes with a Command Line Interface that can be used to convert from Betheseda Plugins to Git Repositories, and back. Note that the UI can also accept these CLI commands, and so this variant is meant for linux machines that cannot handle the UI. It is not self contained, so it might complain about needing a specific .NET runtime downloaded.

This would use Spriggit to convert from a SkyrimSE mod to Yaml, and put it in your Git Repository.

.\Path\To\Spriggit.CLI.exe serialize --InputPath "C:\Games\steamapps\common\Skyrim Special Edition\Data\SomeMod.esp" --OutputPath "C:\MyGitRepository\SomeMod.esp" --GameRelease SkyrimSE --PackageName Spriggit.Yaml

And this would convert it back and overwrite the original mod file.

.\Path\To\Spriggit.CLI.exe deserialize --InputPath "C:\Users\Levia\Downloads\SpriggitOutput\SomeMod.esp" --OutputPath "C:\MyGitRepository\SomeMod.esp"

Spriggit Translation Packages

The logic for actually doing the translation to/from an esp is not housed or packaged directly with the CLI or UI. Rather, the logic exists in NuGet packages that are downloaded and then used to do the translation.

Mechanics

When Spriggit is asked to do a serialization from a Bethesda plugin file to text format, you must provide it with the name of a NuGet package to use for the translation. If a specific version is supplied, it will use that, otherwise it will grab the latest version of that package. As it exports the text files, the NuGet package name and version are included.

When Spriggit is asked to do a deserialization from text to a Bethesda Plugin, no specification of a NuGet package is needed. Rather, it looks in the text files for the listed package + version that was used to make the files in the first place, and downloads that package to use.

As such, a Spriggit CLI/UI can translate to/from many different translation formats/styles, rather than being bound to the translation logic that existed when the CLI/UI was built.

Reasoning

This separation is an important aspect of keeping Spriggit flexible as record definitions evolve.

Especially early on during a game's release, the record definitions are constantly being upgraded, adjusted, and fixed. The separation allows Spriggit to always grab the older version of a translation, and use that to deserialize text that contains older definitions.

If very old versions get deserialized, the older nuget packages will be downloaded and used to read them. And, if the user re-serializes them with the latest nuget packages, they will be "upgraded" to the latest text definitions.

Example

Let's take a simple example of a typo. Let's say Haelth was accidentally used as a field name in v1.1 of Spriggit, and a plugin was serialized into text with that typo. Eventually someone notices, and fixes it to Health in v1.2. How does the old file that contained Haelth get properly read anymore?

It will be able to be read, because the original file will have been stamped with v1.1. During deserialization of the file, Spriggit will see that and download that v1.1 nuget package, and use that to read the file. The Haelth field will be read in as expected by the v1.1 package, yielding a proper esp output.

Customization

Spriggit uses Mutagen systems under the hood, and leans on the Mutagen.Bethesda.Serialization library to convert to/from Yaml and Json.

One of the features of Mutagen.Bethesda.Serialization is that it allows for customization of naming, file structure, and other similar things. If you utilize this to make your own customization, you will need to upload the results to nuget.org for people to grab and use.

More documentation will follow on how to upload your own customization package to Nuget so that it can be used by Spriggit. For now, two packages exist "built in":

These are what will be used to do any translations, unless the user specifies the name of a customization package they wish to use instead.

Check out the Documentation Official Documentation for more detailed explainations of Spriggit, and more typical use cases and examples.