# Mindustry Campaign Stats
Python API and CLI tool to read [Mindustry](https://mindustrygame.github.io/)'s campaign global stats.
  
[PyPI](https://pypi.org/project/mindustry-campaign-stats/) - [Documentation](https://github.com/EpocDotFr/mindustry-campaign-stats?tab=readme-ov-file#usage) - [Source code](https://github.com/EpocDotFr/mindustry-campaign-stats) - [Issue tracker](https://github.com/EpocDotFr/mindustry-campaign-stats/issues) - [Changelog](https://github.com/EpocDotFr/mindustry-campaign-stats/releases)
## Prerequisites
- Python >= 3.10
## Installation
### From PyPi
```shell
pip install mindustry-campaign-stats
```
### Locally
After cloning/downloading the repo:
```shell
pip install .
```
## Usage
### API
The API consists of:
- A `load()` function, which reads data from the given binary file-like object and returns the raw parsed data as
a dictionary
- A `compute()` function, which transforms the above dictionary to a
[`Stats`](https://github.com/EpocDotFr/mindustry-campaign-stats/blob/master/mindustry_campaign_stats/stats.py) instance
- A `Planet` enum (`Serpulo`, `Erekir`) to be used with `compute()`
```python
import mindustry_campaign_stats
from pprint import pprint
try:
with open('settings.bin', 'rb') as fp: # Note it's opened in binary mode
raw_settings = mindustry_campaign_stats.load(fp)
pprint(raw_settings)
computed = mindustry_campaign_stats.compute(
raw_settings,
mindustry_campaign_stats.Planet.Erekir
)
print(computed.totals.storage.capacity)
pprint(
computed.to_dict()
)
except Exception as e:
print(e)
```
### CLI
In its simplest form, the CLI reads data from the given `settings.bin` filename, then writes a human-readable ASCII table
of computed stats to `stdout`. Note you must choose between the `serpulo` or `erekir` campaign.
```shell
mindustry-campaign-stats settings.bin erekir
```
When the `--refresh` option is set, the CLI is running indefinitely, listening for modification in the given `settings.bin`
file until it's terminated. This feature allows the table to be automatically updated in your terminal (screen is cleared
before any update happens).
The `--json` option switches output format to JSON, specifically [JSON Lines](https://jsonlines.org/). The `--pretty`
option may be used to pretty-print the outputted JSON. When `--refresh` is set as well, the CLI will sequentially write
a stream of JSON Lines. Note that `--pretty` is ignored in that case as it would break JSON Lines formatting.
## `settings.bin` format
This file is designed much like a persistent key-value store. It is used to store both user settings and campaigns-related
data. It is formatted as follows (everything is big-endian):
- 4 bytes (int32) - Number of fields to read (`fields_count`)
- Fields sequence (based on `fields_count`):
- 2 bytes (uint16) - Length of the field name (`field_name_length`)
- `field_name_length` bytes - [MUTF-8](https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8)-encoded field name
- 1 byte (int8) - Field type ID (`field_type_id`)
- `field_type_id` value determines how to read the next bytes:
- `0`:
- 1 byte (boolean) - A boolean value
- `1`:
- 4 bytes (int32) - A 32 bits integer
- `2`:
- 8 bytes (int64) - A 64 bits integer
- `3`:
- 4 bytes (float) - A single-precision floating-point number
- `4`:
- 2 bytes (uint16) - Length of the field value (`field_value_length`)
- `field_value_length` bytes - An [MUTF-8](https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8)-encoded string
- `5`:
- 4 bytes (int32) - Length of the field value (`field_value_length`)
- `field_value_length` bytes - A binary value. Most likely [UBJSON](https://en.wikipedia.org/wiki/UBJSON) data
## References
- [Settings.java](https://github.com/Anuken/Arc/blob/v149/arc-core/src/arc/Settings.java)
- [SectorPresets.java](https://github.com/Anuken/Mindustry/blob/v149/core/src/mindustry/content/SectorPresets.java)
- [Items.java](https://github.com/Anuken/Mindustry/blob/v149/core/src/mindustry/content/Items.java)
## Development
### Getting source code and installing the package with dev dependencies
1. Clone the repository
2. From the root directory, run: `pip install -e ".[dev]"`
### Releasing the package
From the root directory, run `python setup.py upload`. This will build the package, create a git tag and publish on PyPI.
`__version__` in `mindustry_campaign_stats/__version__.py` must be updated beforehand. It should adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
An associated GitHub release must be created following the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format.
Raw data
{
"_id": null,
"home_page": "https://github.com/EpocDotFr/mindustry-campaign-stats",
"name": "mindustry-campaign-stats",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "mindustry, settings, reader, stats",
"author": "Maxime \"Epoc\" Gross",
"author_email": "contact.nospam@epoc.nospam.fr",
"download_url": "https://files.pythonhosted.org/packages/f9/9f/3e852da24c337dfe31782c05479947072f8897b2005fc70f12c1074b72bf/mindustry_campaign_stats-2.0.3.tar.gz",
"platform": null,
"description": "\r\n# Mindustry Campaign Stats\r\n\r\nPython API and CLI tool to read [Mindustry](https://mindustrygame.github.io/)'s campaign global stats.\r\n\r\n  \r\n\r\n[PyPI](https://pypi.org/project/mindustry-campaign-stats/) - [Documentation](https://github.com/EpocDotFr/mindustry-campaign-stats?tab=readme-ov-file#usage) - [Source code](https://github.com/EpocDotFr/mindustry-campaign-stats) - [Issue tracker](https://github.com/EpocDotFr/mindustry-campaign-stats/issues) - [Changelog](https://github.com/EpocDotFr/mindustry-campaign-stats/releases)\r\n\r\n## Prerequisites\r\n\r\n - Python >= 3.10\r\n\r\n## Installation\r\n\r\n### From PyPi\r\n\r\n```shell\r\npip install mindustry-campaign-stats\r\n```\r\n\r\n### Locally\r\n\r\nAfter cloning/downloading the repo:\r\n\r\n```shell\r\npip install .\r\n```\r\n\r\n## Usage\r\n\r\n### API\r\n\r\nThe API consists of:\r\n\r\n - A `load()` function, which reads data from the given binary file-like object and returns the raw parsed data as\r\n a dictionary\r\n - A `compute()` function, which transforms the above dictionary to a\r\n [`Stats`](https://github.com/EpocDotFr/mindustry-campaign-stats/blob/master/mindustry_campaign_stats/stats.py) instance\r\n - A `Planet` enum (`Serpulo`, `Erekir`) to be used with `compute()`\r\n\r\n```python\r\nimport mindustry_campaign_stats\r\nfrom pprint import pprint\r\n\r\ntry:\r\n with open('settings.bin', 'rb') as fp: # Note it's opened in binary mode\r\n raw_settings = mindustry_campaign_stats.load(fp)\r\n\r\n pprint(raw_settings)\r\n\r\n computed = mindustry_campaign_stats.compute(\r\n raw_settings,\r\n mindustry_campaign_stats.Planet.Erekir\r\n )\r\n\r\n print(computed.totals.storage.capacity)\r\n\r\n pprint(\r\n computed.to_dict()\r\n )\r\nexcept Exception as e:\r\n print(e)\r\n```\r\n\r\n### CLI\r\n\r\nIn its simplest form, the CLI reads data from the given `settings.bin` filename, then writes a human-readable ASCII table\r\nof computed stats to `stdout`. Note you must choose between the `serpulo` or `erekir` campaign.\r\n\r\n```shell\r\nmindustry-campaign-stats settings.bin erekir\r\n```\r\n\r\nWhen the `--refresh` option is set, the CLI is running indefinitely, listening for modification in the given `settings.bin`\r\nfile until it's terminated. This feature allows the table to be automatically updated in your terminal (screen is cleared\r\nbefore any update happens).\r\n\r\nThe `--json` option switches output format to JSON, specifically [JSON Lines](https://jsonlines.org/). The `--pretty`\r\noption may be used to pretty-print the outputted JSON. When `--refresh` is set as well, the CLI will sequentially write\r\na stream of JSON Lines. Note that `--pretty` is ignored in that case as it would break JSON Lines formatting.\r\n\r\n## `settings.bin` format\r\n\r\nThis file is designed much like a persistent key-value store. It is used to store both user settings and campaigns-related\r\ndata. It is formatted as follows (everything is big-endian):\r\n\r\n- 4 bytes (int32) - Number of fields to read (`fields_count`)\r\n- Fields sequence (based on `fields_count`):\r\n - 2 bytes (uint16) - Length of the field name (`field_name_length`)\r\n - `field_name_length` bytes - [MUTF-8](https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8)-encoded field name\r\n - 1 byte (int8) - Field type ID (`field_type_id`)\r\n - `field_type_id` value determines how to read the next bytes:\r\n - `0`:\r\n - 1 byte (boolean) - A boolean value\r\n - `1`:\r\n - 4 bytes (int32) - A 32 bits integer\r\n - `2`:\r\n - 8 bytes (int64) - A 64 bits integer\r\n - `3`:\r\n - 4 bytes (float) - A single-precision floating-point number\r\n - `4`:\r\n - 2 bytes (uint16) - Length of the field value (`field_value_length`)\r\n - `field_value_length` bytes - An [MUTF-8](https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8)-encoded string\r\n - `5`:\r\n - 4 bytes (int32) - Length of the field value (`field_value_length`)\r\n - `field_value_length` bytes - A binary value. Most likely [UBJSON](https://en.wikipedia.org/wiki/UBJSON) data\r\n\r\n## References\r\n\r\n - [Settings.java](https://github.com/Anuken/Arc/blob/v149/arc-core/src/arc/Settings.java)\r\n - [SectorPresets.java](https://github.com/Anuken/Mindustry/blob/v149/core/src/mindustry/content/SectorPresets.java)\r\n - [Items.java](https://github.com/Anuken/Mindustry/blob/v149/core/src/mindustry/content/Items.java)\r\n\r\n## Development\r\n\r\n### Getting source code and installing the package with dev dependencies\r\n\r\n 1. Clone the repository\r\n 2. From the root directory, run: `pip install -e \".[dev]\"`\r\n\r\n### Releasing the package\r\n\r\nFrom the root directory, run `python setup.py upload`. This will build the package, create a git tag and publish on PyPI.\r\n\r\n`__version__` in `mindustry_campaign_stats/__version__.py` must be updated beforehand. It should adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\r\n\r\nAn associated GitHub release must be created following the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format.\r\n",
"bugtrack_url": null,
"license": "DBAD",
"summary": "Python API and CLI tool to read Mindustry's campaign global stats.",
"version": "2.0.3",
"project_urls": {
"Changelog": "https://github.com/EpocDotFr/mindustry-campaign-stats/releases",
"Documentation": "https://github.com/EpocDotFr/mindustry-campaign-stats?tab=readme-ov-file#usage",
"Homepage": "https://github.com/EpocDotFr/mindustry-campaign-stats",
"Issue tracker": "https://github.com/EpocDotFr/mindustry-campaign-stats/issues",
"Source code": "https://github.com/EpocDotFr/mindustry-campaign-stats"
},
"split_keywords": [
"mindustry",
" settings",
" reader",
" stats"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "0911a7807f75f33db4c24ddc8544448bd54b0b11a287c6b420a9b3bf50099803",
"md5": "cdaa8567dd7a468002844e40a1410866",
"sha256": "146b5ccbeebde4d66b14542862819caac80472ad43f548244e71c8f68c20810b"
},
"downloads": -1,
"filename": "mindustry_campaign_stats-2.0.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "cdaa8567dd7a468002844e40a1410866",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 11494,
"upload_time": "2025-07-08T19:23:17",
"upload_time_iso_8601": "2025-07-08T19:23:17.663765Z",
"url": "https://files.pythonhosted.org/packages/09/11/a7807f75f33db4c24ddc8544448bd54b0b11a287c6b420a9b3bf50099803/mindustry_campaign_stats-2.0.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "f99f3e852da24c337dfe31782c05479947072f8897b2005fc70f12c1074b72bf",
"md5": "02df5dd1ea20d9c261d0e1b10eeb4a60",
"sha256": "52e3f6c9f2e4c53d1200724ac744420274522da15c09dc675a7c3ba6e1c8e8c7"
},
"downloads": -1,
"filename": "mindustry_campaign_stats-2.0.3.tar.gz",
"has_sig": false,
"md5_digest": "02df5dd1ea20d9c261d0e1b10eeb4a60",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 12995,
"upload_time": "2025-07-08T19:23:18",
"upload_time_iso_8601": "2025-07-08T19:23:18.810193Z",
"url": "https://files.pythonhosted.org/packages/f9/9f/3e852da24c337dfe31782c05479947072f8897b2005fc70f12c1074b72bf/mindustry_campaign_stats-2.0.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-08 19:23:18",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "EpocDotFr",
"github_project": "mindustry-campaign-stats",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "mindustry-campaign-stats"
}