git clone https://github.com/MostGenerousDev/GK-ModUpdater
cd gkmodkit
python gkupdate.py tools # tells you what helpers are missing
python gkupdate.py --helpNo dependencies beyond the standard library. Python 3.10+.
python -m unittest discover -s tests -t . -vThey 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.
pip install ruff
ruff check .pip install pyinstaller
python build.pyThat 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.
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.
Two load-bearing rules:
-
Export bundles can only be merged when a package has no external arcs. GraphData arcs carry a
ToExportBundleIndexpointing 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 address0x10. -
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.