Skip to content

Latest commit

 

History

History
79 lines (57 loc) · 2.68 KB

File metadata and controls

79 lines (57 loc) · 2.68 KB

Contributing

Running it from source

git clone https://github.com/MostGenerousDev/GK-ModUpdater
cd gkmodkit
python gkupdate.py tools       # tells you what helpers are missing
python gkupdate.py --help

No dependencies beyond the standard library. Python 3.10+.

Tests

python -m unittest discover -s tests -t . -v

They don't need the game, retoc, repak, or a network connection. Anything that touches config redirects LOCALAPPDATA at a temp folder first, so running the suite can't clobber a real install or a real config.

tests/builders.py constructs synthetic containers and zen packages byte for byte. Add new structures there rather than checking in binary fixtures: a hand-built structure documents the layout and fails loudly when it is wrong.

Where a test asserts a specific hash or offset, note in a comment which real file the value came from.

Lint

pip install ruff
ruff check .

Building the executable

pip install pyinstaller
python build.py

That produces an onedir build. --onefile works, but the self-extracting stub trips generic antivirus heuristics; Windows Defender quarantines such builds on sight, so don't use it for anything you hand to other people.

Always run what you built, not just build it. A successful build is not proof the result launches.

Design notes

The library never calls sys.exit(). It raises from gkmodkit.errors; the CLI maps those to messages and exit codes. gkmodkit is a library, so if you want to exit from inside it, add an exception type instead. Nothing in the library prints, either.

No third-party binaries in the repo or the release. retoc and repak belong to their authors under their own licences. gkmodkit/tools.py locates a copy or downloads one on explicit request. Please don't vendor them.

Byte layouts belong in formats.py. Anything that reads or writes an engine structure goes there, with the layout written out in the docstring. The rest of the codebase should never unpack a struct directly.

Things worth knowing before changing the converter

Two load-bearing rules:

  1. Export bundles can only be merged when a package has no external arcs. GraphData arcs carry a ToExportBundleIndex pointing at a bundle of the package being loaded. Collapse a package that has arcs and they dangle; the loader walks off the bundle array and the game dies reading address 0x10.

  2. Two mods must never provide the same PackageId. Overriding a base game package is normal and how mods work. Two mods claiming one package is a common crash, but that is a mod manager's concern, so GK-ModUpdater leaves conflict handling to GK-ModLoader.