Python utilities for Starbound files, plus shipworld rendering and mod generation
Project description
py-starbound
Python utilities for Starbound files, plus shipworld rendering and mod generation.
File & data formats
See FORMATS.md for technical details on Starbound’s formats (BTreeDB5, SBAsset6, SBVJ01, SBON, worlds).
Installation
- Recommended (editable):
- Core only:
python -m pip install -e .
- With image features (Pillow) for render/modgen and related tests:
python -m pip install -e '.[ship]'
CLI commands (pystarbound)
CLI examples
- Extract a .pak/.modpak to a directory
pystarbound export /Starbound/assets/packed.pak -d assets
- Print world region info (tiles or entities)
# Pretty-print tiles for the region containing the player spawn
pystarbound region "/Starbound/storage/universe/-382912739_-582615456_-73870035_3.world"
# Print a specific region and value (e.g., liquid_pressure)
pystarbound region --value-index=12 \
"/Starbound/storage/universe/-382912739_-582615456_-73870035_3.world" 69 27
# Print entities in a region
pystarbound region --entities \
"/Starbound/storage/universe/-382912739_-582615456_-73870035_3.world" 69 27
- World selection workflow (preview → requires → extract)
# Preview a player-built area by seed/flood-fill, with padding
pystarbound world-preview /path/to/world.world -o preview.png \
--assets "/path/to/vanilla:/path/to/mods" \
--seed 123,456 --seed-mode any --pad 2
# See which mods are required for that selection
pystarbound world-requires /path/to/world.world --json \
--assets "/path/to/vanilla:/path/to/mods" \
--seed 123,456 --pad 2 --objects --objects-only-known
# Extract the same selection as an installable mod, with objects and BYOS
pystarbound world-extract /path/to/world.world -o out/mod/export \
--assets "/path/to/vanilla:/path/to/mods" \
--seed 123,456 --pad 2 \
--objects --objects-only-known --byos
- Publish a directory to .pak
pystarbound publish ./folder -o out.pak \
--only 'assets/*' --exclude '*.skip' --strip-prefix 'assets' \
--metadata meta.json --meta author=py-starbound
- Export packaged assets:
# List only
pystarbound export --list /path/to/packed.pak
# Extract
pystarbound export /path/to/packed.pak -d out/dir
- Publish directory to .pak:
pystarbound publish ./folder -o out.pak \
--only 'assets/*' --exclude '*.skip' --strip-prefix 'assets' \
--metadata meta.json --meta author=py-starbound
- Verify package integrity:
pystarbound verify out.pak
- Versioned JSON:
pystarbound vjson-dump input.sbvj01 -o out.json
pystarbound vjson-make in.json -o out.sbvj01
# Edit: deep-merge a JSON patch and set/append fields
pystarbound vjson-edit in.sbvj01 --patch patch.json --set 'identity.name="Beta"' \
--append 'tags="t1"' --append 'tags="t2"' -o out_edited.sbvj01
- Render shipworld to PNG (requires extras [ship]):
pystarbound render /path/to/file.shipworld --assets '/path/to/vanilla:/path/to/mods' -o ship.png
- World preview: layers, dungeon overlays, legend (requires extras [ship]):
# Only foreground, draw dungeon bounding boxes and labels, and write a legend of material colors used
pystarbound world-preview /path/to/world.world -o preview.png \
--assets '/path/to/vanilla:/path/to/mods' \
--layers fg --overlay-dungeons --overlay-dungeon-labels \
--legend legend.json
- Export selection to a Tiled-like JSON (experimental):
# Export a cropped area as a Tiled-like JSON with material IDs stored in CSV tile layers
pystarbound world-export-tiled /path/to/world.world \
--rect 100,200,200,260 --pad 2 -o out/map.json
- Workshop: list and sync (no login required):
# List installed Workshop items (JSON)
pystarbound workshop list --json
# Dry-run sync of contents.pak into Starbound/mods
pystarbound workshop sync --dry-run
# Symlink (or copy if not supported)
pystarbound workshop sync --link
- Workshop: prepare/pack/verify modsets:
# Prepare a filtered modset (by IDs)
pystarbound workshop prepare --out-dir ./modset --ids 12345,67890
# Prepare by title substrings (case-insensitive) listed in a file (one per line)
pystarbound workshop prepare --out-dir ./modset --titles-file titles.txt
# Prepare with glob patterns on id/title
pystarbound workshop prepare --out-dir ./modset --only 'X-*' --exclude '*old*'
# Pack a prepared directory into a .pak
pystarbound workshop pack --dir ./modset -o modset.pak
# Verify all .pak files in a directory
pystarbound workshop verify --dir ./modset --json
- Generate a mod from a shipworld (requires extras [ship]):
pystarbound modgen /path/to/file.shipworld \
--assets '/path/to/vanilla:/path/to/mods' \
-o out/mod/export \
[--background-overlay] [--objects [--objects-only-known] [--objects-log-unknown path.json]] \
[--material-map material_map.json]
- World selection preview (PNG):
pystarbound world-preview /path/to/world.world -o preview.png \
--assets '/path/to/vanilla:/path/to/mods' \
[--dungeon-id N | --rect x0,y0,x1,y1 | --seed x,y [--seed-mode any|fg|bg]] [--pad 2] [--textured] [--no-crop]
- Extract a structure from a planet/world:
pystarbound world-extract /path/to/world.world \
--assets '/path/to/vanilla:/path/to/mods' \
-o out/mod/export \
[--dungeon-id N | --rect x0,y0,x1,y1 | --seed x,y [--seed-mode any|fg|bg] [--seed-connectivity four|eight]] [--pad 2] \
[--background-overlay] [--objects [--objects-only-known] [--objects-log-unknown path.json]] \
[--object-map objects.json] [--materials-include 1,2,3] [--materials-exclude 12345] \
[--objects-include name1,name2] [--objects-exclude 'glob*'] [--blocks-position x,y] \
[--requires-into-metadata] [--report report.json] [--pack] [--pack-out out.pak]
- Batch export dungeons by id or by size:
# Specific dungeon ids
pystarbound world-extract /path/to/world.world -o out/mod/export \
--assets "/path/to/vanilla:/path/to/mods" \
--dungeon-ids 12,17,33 --pack
# Top 3 dungeons by tile count (min 500 tiles)
pystarbound world-extract /path/to/world.world -o out/mod/export \
--assets "/path/to/vanilla:/path/to/mods" \
--top-dungeons 3 --min-tiles 500 --pack --combined-patch combined_universe_server.config.patch
- List dungeons present in a world (optionally with bounding boxes):
pystarbound world-dungeons /path/to/world.world [--bbox] [--json] [--min-tiles 100]
- Analyze required mods for a selection (no export):
pystarbound world-requires /path/to/world.world \
--assets '/path/to/vanilla:/path/to/mods' \
[--dungeon-id N | --rect x0,y0,x1,y1 | --seed x,y [--seed-mode any|fg|bg]] [--pad 2] \
[--objects [--objects-only-known]] [--json]
Assets roots
- Use your OS path separator when passing multiple roots to
--assets:- macOS/Linux:
: - Windows:
;
- macOS/Linux:
Examples:
# macOS/Linux
--assets "/path/to/vanilla:/path/to/mods"
# Windows (PowerShell/cmd)
--assets "C:\Starbound\assets;C:\Starbound\mods"
- When you pass a directory root to
--assets, any.pakfiles inside it are automatically scanned. Material names andmapColorare read from.pakas well, so previews andblockKeynaming work for.pak-only mods. Provenance (world-requiresandrequires.json) also includes.pakmods discovered under those directories.
Notes
- Mod id default: when
--mod-idis omitted, it is derived from the world filename (sanitized to[a-z0-9_-]). - Previews:
--texturednow reads texture paths from each material’s.material(renderParameters.texture) and loads from both directories and.pakfiles when available. It falls back to mapColor when textures are missing. --no-croprenders the full world extents (default behavior crops to nonzero tiles).- Textures are not bundled; Starbound renders installed materials at runtime.
- Unknown materials:
- Provide assets roots with
--assets - Or map manually via
--material-mapwith a JSON mapping, for example:
- Provide assets roots with
{"12345": "modid:materialName"}
Testing
# All tests
pytest -q
# Single file
pytest tests/test_cli_publish_export.py -q
# Single test
pytest tests/test_cli_publish_export.py::test_publish_export_roundtrip -q
Note: Image-related tests require Pillow via extras:
python -m pip install -e '.[ship]'
Build (PEP 517 via setuptools)
python -m pip install -U build
python -m build
Artifacts are written to dist/.
Running from source (without install)
- Detect Starbound installation (Steam paths):
pystarbound detect-install --json
If you prefer not to install during development, invoke the CLI via the module entrypoint. Ensure you set PYTHONPATH to include src/:
PYTHONPATH=src python3 -m starbound.cli <command> [options]
# examples
PYTHONPATH=src python3 -m starbound.cli export --list /path/to/packed.pak
PYTHONPATH=src python3 -m starbound.cli region /path/to/world.world --entities
Using the Python package
Example: Reading a player file
import starbound
with open('player/11475cedd80ead373c19a91de2e2c4d3.player', 'rb') as fh:
player = starbound.read_sbvj01(fh)
print('Hello, {}!'.format(player.data['identity']['name']))
Example: World files (fast with mmap)
import mmap, starbound
with open('universe/43619853_198908799_-9440367_6_3.world', 'rb') as fh:
mm = mmap.mmap(fh.fileno(), 0, access=mmap.ACCESS_READ)
world = starbound.World(mm)
world.read_metadata()
print('World size: {}×{}'.format(world.width, world.height))
x, y = world.metadata['playerStart']
print('Player spawns at ({}, {})'.format(x, y))
# Regions consist of 32×32 tiles.
rx, ry = int(x) // 32, int(y) // 32
print('An entity:', world.get_entities(rx, ry)[0])
Example: Easy access to various world attributes
import starbound
# Assume 'world' from the example above
info = world.info
print('World Name:', info.name)
print('World Description:', info.description)
print('World Coordinates:', info.coords)
Example: Getting assets from packed.pak
import starbound
with open('assets/packed.pak', 'rb') as fh:
package = starbound.SBAsset6(fh)
print(package.get('/lighting.config'))
Example: Finding an entity by UUID/ID
Many entities (flags, mech beacons, quest markers, etc.) have UUIDs or IDs the game uses to locate them. You can use World.get_entity_uuid_coords to locate the tile coordinates quickly when the index is present:
import mmap, starbound
with open('universe/43619853_198908799_-9440367_6_3.world', 'rb') as fh:
mm = mmap.mmap(fh.fileno(), 0, access=mmap.ACCESS_READ)
world = starbound.World(mm)
world.read_metadata()
mechbeacon_coords = world.get_entity_uuid_coords('mechbeacon')
if mechbeacon_coords:
print('Mech beacon at', mechbeacon_coords)
else:
print('No mech beacon in level!')
Example: Modifying SBVJ01 files (players, client contexts)
import starbound
with open('player/420ed511f83b3760dead42a173339b3e.player', 'r+b') as fh:
player = starbound.read_sbvj01(fh)
old_name = player.data['identity']['name']
new_name = old_name[::-1] # example transform
player.data['identity']['name'] = new_name
print('Updating name: {} -> {}'.format(old_name, new_name))
# Rewrite file with updated data
fh.seek(0)
starbound.write_sbvj01(fh, player)
fh.truncate()
Credits
- Core: Blixt
- Contributions and enhancements: Xytronix
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pstarbound-1.3.0.tar.gz.
File metadata
- Download URL: pstarbound-1.3.0.tar.gz
- Upload date:
- Size: 51.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a3263f2b0924a7355efb480f0c987a82b367765de2029aff12ef444c6faac66
|
|
| MD5 |
ef525dd75ef85f7685020cf8187e24c1
|
|
| BLAKE2b-256 |
bd3fcd3bc71965ad448ffde52db4b64c5d6ed212a25fae560a9904ce6a9b2917
|
Provenance
The following attestation bundles were made for pstarbound-1.3.0.tar.gz:
Publisher:
publish.yml on Xytronix/py-starbound
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pstarbound-1.3.0.tar.gz -
Subject digest:
6a3263f2b0924a7355efb480f0c987a82b367765de2029aff12ef444c6faac66 - Sigstore transparency entry: 545471823
- Sigstore integration time:
-
Permalink:
Xytronix/py-starbound@dba06da82333775e73998097d04b755e92ada51d -
Branch / Tag:
refs/tags/v1.3.0 - Owner: https://github.com/Xytronix
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dba06da82333775e73998097d04b755e92ada51d -
Trigger Event:
release
-
Statement type:
File details
Details for the file pstarbound-1.3.0-py3-none-any.whl.
File metadata
- Download URL: pstarbound-1.3.0-py3-none-any.whl
- Upload date:
- Size: 53.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc942aba5e40c8ff4a2ef96738fe5042ba72df835bbc7b2de6dddea01b68a318
|
|
| MD5 |
4cc696ec1eedeef3748c03d152716b2e
|
|
| BLAKE2b-256 |
9e80cfbddf67832e3f47b9f6f6f993a78e9c009ff180c339d671951454d5b57b
|
Provenance
The following attestation bundles were made for pstarbound-1.3.0-py3-none-any.whl:
Publisher:
publish.yml on Xytronix/py-starbound
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pstarbound-1.3.0-py3-none-any.whl -
Subject digest:
cc942aba5e40c8ff4a2ef96738fe5042ba72df835bbc7b2de6dddea01b68a318 - Sigstore transparency entry: 545471824
- Sigstore integration time:
-
Permalink:
Xytronix/py-starbound@dba06da82333775e73998097d04b755e92ada51d -
Branch / Tag:
refs/tags/v1.3.0 - Owner: https://github.com/Xytronix
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@dba06da82333775e73998097d04b755e92ada51d -
Trigger Event:
release
-
Statement type: