Complete toolkit for:
- Modmaker (texture export/edit)
- Runtime modloader (BepInEx + runtime overlay from
Mods/) - GUI frontend
- Optional direct patch + restore workflow
Current release line: 0.2.3-beta.1
Change history: changelog.txt
mainbranch: core modkit (CLI, GUI, loader, runtime merge)buildtoolsbranch: packaging/release build scripts
GitHub links:
- Main:
https://github.com/metl-group/ucs-modkit - Buildtools branch:
https://github.com/metl-group/ucs-modkit/tree/buildtools
Quick clone:
git clone https://github.com/metl-group/ucs-modkit.git
cd ucs-modkitcd /path/to/ucs-modkit
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txtOptional (build C# loader plugin):
curl -fsSL https://dot.net/v1/dotnet-install.sh | bash -s -- --channel 8.0 --install-dir "$HOME/.local/share/dotnet"GAME="/path/to/steamapps/common/Used Cars Simulator"- Install loader (BepInEx + UCS plugin):
cd /path/to/ucs-modkit
. .venv/bin/activate
python ucs_modkit.py install-loader --game-dir "$GAME"- Set launch option (Linux/Proton only):
WINEDLLOVERRIDES="winhttp=n,b" %command%
- Export textures:
python ucs_modkit.py export --game-dir "$GAME" --mod my_first_mod --scope bundles- Edit PNGs in:
$GAME/Mods/my_first_mod/textures/
- Build runtime overrides:
python ucs_modkit.py package --game-dir "$GAME" --mod my_first_modDefault behavior includes both .bundle and .assets containers.
Use --bundles-only if you explicitly want bundle-only packaging.
Optional (small redistributable, archive-style delta mod):
python ucs_modkit.py package --game-dir "$GAME" --mod my_first_mod --archive-deltas --archive-only --prune-archived--prune-archived is non-destructive: it creates a flat release/<mod>.zip with:
manifest.jsonmod.inioverrides.map- only changed/delta
textures/*.png
No nested ZIPs are included (NexusMods-friendly).
If --archive-deltas is not set, no archives/ folder is created.
- Enable/disable and set priority (global in
Mods/mods.ini):
python ucs_modkit.py set-mod --game-dir "$GAME" --mod my_first_mod --enabled true --priority 10Mods/mods.ini example:
mod.my_first_mod.enabled=true
mod.my_first_mod.priority=10- Rebuild modular runtime merge:
python ucs_modkit.py merge-runtime --game-dir "$GAME"merge-runtime always rebuilds a clean output mod from scratch. Manual pre-clean is not required.
Windows: no launch option is required.
Generated merge mod output:
$GAME/Mods/_runtime_merged/
cd /path/to/ucs-modkit
./run_gui.shGUI controls:
- Export
- Export 3D models (OBJ)
- Package
- Loader build/install
- Mod enable/disable/global priority (
Mods/mods.ini) - Runtime merge rebuild/clean
This toolkit can be packaged for non-technical users:
- Linux: AppImage (
UCS-Modkit-linux-x86_64.AppImage) - Windows: portable
.exebundle +.zip
Build scripts are maintained in the buildtools branch of this repository.
Compatibility wrappers remain in packaging/ in this branch.
git clone -b buildtools https://github.com/metl-group/ucs-modkit.git ucs-modkit-buildtools
cd ucs-modkit-buildtools
./build_linux_appimage.shOutput:
dist/UCS-Modkit-linux-x86_64.AppImage
Offline distribution profile (lobotomized):
UCS_MODKIT_PROFILE=lobotomized ./build_linux_appimage.shOutput:
dist/UCS-Modkit-linux-lobotomized-x86_64.AppImage
Build on a Windows machine (PyInstaller cannot cross-compile from Linux):
cd C:\path\to\ucs-modkit-buildtools
.\build_windows_release.ps1 -ModkitRoot C:\path\to\ucs-modkitOutputs:
dist/UCS-Modkit-windows\ucs_modkit_gui\ucs_modkit_gui.exedist/UCS-Modkit-windows\ucs_modkit_gui\ucs_modkit_cli.exedist/UCS-Modkit-windows\ucs_modkit_cli.exedist/UCS-Modkit-windows.zip
Offline distribution profile (lobotomized):
.\build_windows_release.ps1 -ModkitRoot C:\path\to\ucs-modkit -Profile lobotomizedOutputs:
dist/UCS-Modkit-windows-lobotomized\...dist/UCS-Modkit-windows-lobotomized.zip
Note: Windows defaults to GUI onedir packaging (better AV compatibility).
You can force onefile with -Layout onefile.
Both packaged versions keep loader installation support through the GUI/CLI (install-loader), including Windows game installs (no Proton required).
Compatibility wrappers still exist under packaging/, but the canonical build entrypoint is the buildtools branch.
- Export:
cd /path/to/ucs-modkit
. .venv/bin/activate
python ucs_modkit.py export --game-dir "$GAME" --mod my_first_mod --scope all- Edit PNGs in:
$GAME/Mods/my_first_mod/textures/
- Apply mod directly:
python ucs_modkit.py apply --game-dir "$GAME" --mod my_first_mod- Restore originals:
python ucs_modkit.py restore --game-dir "$GAME"Scan textures:
python ucs_modkit.py scan --game-dir "$GAME" --scope allScan 3D models:
python ucs_modkit.py scan-models --game-dir "$GAME" --scope all --output meshes.jsonExport 3D models (OBJ) into a mod folder:
python ucs_modkit.py export-models --game-dir "$GAME" --mod model_lab --scope allExport only matching names (regex):
python ucs_modkit.py export --game-dir "$GAME" --mod ui_mod --name-filter "icon|thumbnail|brand"Build runtime override package:
python ucs_modkit.py package --game-dir "$GAME" --mod ui_modBuild archive-only delta mod (small upload size):
python ucs_modkit.py package --game-dir "$GAME" --mod ui_mod --archive-deltas --archive-only --prune-archivedNote: --archive-only requires --archive-deltas.
Default alpha handling is preserve (recommended for character/clothing textures).
To use edited alpha as-is (advanced/risky), pass --alpha-mode keep.
Bundle-only packaging:
python ucs_modkit.py package --game-dir "$GAME" --mod ui_mod --bundles-onlyForce opaque alpha (debug/helper):
python ucs_modkit.py package --game-dir "$GAME" --mod ui_mod --alpha-mode opaqueBuild runtime merge (all active mods):
python ucs_modkit.py merge-runtime --game-dir "$GAME"Bundle-only merge:
python ucs_modkit.py merge-runtime --game-dir "$GAME" --bundles-onlyUse edited alpha during merge (advanced/risky):
python ucs_modkit.py merge-runtime --game-dir "$GAME" --alpha-mode keepDelete merge output:
python ucs_modkit.py clean-merged --game-dir "$GAME"Apply all mods directly (legacy flow):
python ucs_modkit.py apply --game-dir "$GAME" --allShow status:
python ucs_modkit.py status --game-dir "$GAME"Show status as JSON:
python ucs_modkit.py status --game-dir "$GAME" --jsonClassic runtime override mod:
Mods/<mod_name>/
mod.ini
overrides.map
overrides/...
manifest.json
Flat release ZIP mod (recommended for upload/sharing):
Mods/<mod_name>.zip
manifest.json
mod.ini
overrides.map
textures/*.png
Optional folder-based delta mod (advanced/internal):
Mods/<mod_name>/
manifest.json
archives/delta_textures.zip
optional mod.ini
Notes:
- Flat ZIP mods are read directly by
merge-runtime(no extraction required). merge-runtimecan merge folder mods and.zipmods together.- Global
enabled/priorityare controlled inMods/mods.ini, not inside each mod. - Multiple mods can touch the same bundle; conflict resolution still uses priority (higher wins).
- Many NPC clothing/body textures are shared atlases used by multiple NPCs.
- If alpha is zeroed, shaders can hide whole meshes (can look like all NPCs disappear).
- Modkit defaults to
--alpha-mode preserveto keep original alpha while applying RGB edits. - Use
--alpha-mode keeponly when you intentionally want alpha changes and have tested the result.
Suggested clothing test loop:
- Build with
--alpha-mode preserve. - Run in-game and verify body remains visible for all NPC variants.
- Only then experiment with
--alpha-mode keepon selected assets.
- Runtime mods live under
Mods/<mod>/with:manifest.json- optional
mod.ini - either
overrides.map + overrides/...orarchives/*.zip
- ZIP mods can be dropped directly as
Mods/<mod>.zip(manifest/mod.ini/overrides.map/textures). - Global mod settings live in:
Mods/mods.ini - Merger generates a combined mod in
Mods/_runtime_merged. - Conflict rule: higher
prioritywins; conflicts are written tomerge_report.json. statusnow reports runtime entry count when available (runtime_overrides.entry_count), not full export size.- Backups for direct patch mode are under:
$GAME/Mods/.ucs_backups/ applywrites only changed PNGs by default (hash compare).--forcere-applies all PNGs from the mod.export --forcedeletes existing exported PNGs in the mod folder.